From 7ef8270ddac1d8eb91647b9abd5e1cfc9d5a48ec Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Wed, 20 Jun 2018 21:03:34 +0000 Subject: [PATCH 001/495] [CMake] Convert paths to the right form in standalone builds on Windows The paths output from llvm-config --cmakedir and from clang --print-libgcc-file-name can contain backslashes, while CMake can't handle the paths in this form. This matches what compiler-rt already does (since SVN r203789 and r293195). Differential Revision: https://reviews.llvm.org/D48356 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@335172 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/Modules/HandleCompilerRT.cmake | 3 +++ cmake/Modules/HandleOutOfTreeLLVM.cmake | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cmake/Modules/HandleCompilerRT.cmake b/cmake/Modules/HandleCompilerRT.cmake index e9da3c43a..2e0e69e5e 100644 --- a/cmake/Modules/HandleCompilerRT.cmake +++ b/cmake/Modules/HandleCompilerRT.cmake @@ -14,6 +14,7 @@ function(find_compiler_rt_library name dest) OUTPUT_VARIABLE LIBRARY_FILE ) string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE) + file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE) string(REPLACE "builtins" "${name}" LIBRARY_FILE "${LIBRARY_FILE}") if (NOT HAD_ERROR AND EXISTS "${LIBRARY_FILE}") message(STATUS "Found compiler-rt library: ${LIBRARY_FILE}") @@ -37,6 +38,7 @@ function(find_compiler_rt_dir dest) OUTPUT_VARIABLE LIBRARY_DIR ) string(STRIP "${LIBRARY_DIR}" LIBRARY_DIR) + file(TO_CMAKE_PATH "${LIBRARY_DIR}" LIBRARY_DIR) set(LIBRARY_DIR "${LIBRARY_DIR}/darwin") else() set(CLANG_COMMAND ${CMAKE_CXX_COMPILER} ${LIBCXX_COMPILE_FLAGS} @@ -47,6 +49,7 @@ function(find_compiler_rt_dir dest) OUTPUT_VARIABLE LIBRARY_FILE ) string(STRIP "${LIBRARY_FILE}" LIBRARY_FILE) + file(TO_CMAKE_PATH "${LIBRARY_FILE}" LIBRARY_FILE) get_filename_component(LIBRARY_DIR "${LIBRARY_FILE}" DIRECTORY) endif() if (NOT HAD_ERROR AND EXISTS "${LIBRARY_DIR}") diff --git a/cmake/Modules/HandleOutOfTreeLLVM.cmake b/cmake/Modules/HandleOutOfTreeLLVM.cmake index 83948b14f..70eed1d70 100644 --- a/cmake/Modules/HandleOutOfTreeLLVM.cmake +++ b/cmake/Modules/HandleOutOfTreeLLVM.cmake @@ -46,10 +46,11 @@ macro(find_llvm_parts) OUTPUT_VARIABLE CONFIG_OUTPUT ERROR_QUIET) if(NOT HAD_ERROR) - string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH) + string(STRIP "${CONFIG_OUTPUT}" LLVM_CMAKE_PATH_FROM_LLVM_CONFIG) + file(TO_CMAKE_PATH "${LLVM_CMAKE_PATH_FROM_LLVM_CONFIG}" LLVM_CMAKE_PATH) else() - set(LLVM_CMAKE_PATH - "${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") + file(TO_CMAKE_PATH "${LLVM_BINARY_DIR}" LLVM_BINARY_DIR_CMAKE_STYLE) + set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm") endif() else() set(LLVM_FOUND OFF) -- GitLab From 1639392a4af6150c69d77bbda1327b2fbce8c293 Mon Sep 17 00:00:00 2001 From: Matt Morehouse Date: Mon, 25 Jun 2018 18:01:51 +0000 Subject: [PATCH 002/495] [CMake] Fix install-cxx target. Was broken by r334477. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@335507 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 8916ae7f4..90f6dcf6b 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -255,7 +255,7 @@ if (LIBCXX_INSTALL_HEADERS) if (NOT CMAKE_CONFIGURATION_TYPES) add_custom_target(install-cxx-headers - DEPENDS cxx-headers ${generated_config_deps} + DEPENDS cxx_headers ${generated_config_deps} COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cxx-headers -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") -- GitLab From 4d66f0966a052f96f27c068eefa0c916fdff22b8 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Thu, 28 Jun 2018 03:11:52 +0000 Subject: [PATCH 003/495] Support for multiarch runtimes layout This change adds a support for multiarch style runtimes layout, so in addition to the existing layout where runtimes get installed to: lib/clang/$version/lib/$os Clang now allows runtimes to be installed to: lib/clang/$version/$target/lib This also includes libc++, libc++abi and libunwind; today those are assumed to be in Clang library directory built for host, with the new layout it is possible to install libc++, libc++abi and libunwind into the runtime directory built for different targets. The use of new layout is enabled by setting the LLVM_ENABLE_RUNTIME_TARGET_DIR CMake variable and is supported by both projects and runtimes layouts. The runtimes CMake build has been further modified to use the new layout when building runtimes for multiple targets. Differential Revision: https://reviews.llvm.org/D45604 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@335809 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 20 +++++++++++++++----- cmake/Modules/HandleLibCXXABI.cmake | 2 +- include/CMakeLists.txt | 6 +++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53ad1ffea..b6b8babad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -378,20 +378,30 @@ endif () set(LIBCXX_COMPILER ${CMAKE_CXX_COMPILER}) set(LIBCXX_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(LIBCXX_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set(LIBCXX_HEADER_DIR ${LLVM_BINARY_DIR}) set(LIBCXX_BINARY_INCLUDE_DIR "${LIBCXX_BINARY_DIR}/include/c++build") -if (LLVM_LIBRARY_OUTPUT_INTDIR) + +string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION + ${PACKAGE_VERSION}) + +if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) + set(DEFAULT_INSTALL_PREFIX lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/) + set(DEFAULT_INSTALL_HEADER_PREFIX lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/) + set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/lib${LLVM_RUNTIMES_LIBDIR_SUFFIX}) + set(LIBCXX_HEADER_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}) +elseif(LLVM_LIBRARY_OUTPUT_INTDIR) set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) else() set(LIBCXX_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXX_LIBDIR_SUFFIX}) endif() + file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}") -set(LIBCXX_INSTALL_PREFIX "" CACHE STRING +set(LIBCXX_INSTALL_PREFIX ${DEFAULT_INSTALL_PREFIX} CACHE STRING "Define libc++ destination prefix.") -if (NOT LIBCXX_INSTALL_PREFIX MATCHES "^$|.*/") - message(FATAL_ERROR "LIBCXX_INSTALL_PREFIX has to end with \"/\".") -endif() +set(LIBCXX_INSTALL_HEADER_PREFIX ${DEFAULT_INSTALL_HEADER_PREFIX} CACHE STRING + "Define libc++ header destination prefix.") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR}) diff --git a/cmake/Modules/HandleLibCXXABI.cmake b/cmake/Modules/HandleLibCXXABI.cmake index e3a8d0224..797b504eb 100644 --- a/cmake/Modules/HandleLibCXXABI.cmake +++ b/cmake/Modules/HandleLibCXXABI.cmake @@ -65,7 +65,7 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs) if (LIBCXX_INSTALL_HEADERS) install(FILES "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}" - DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1/${dstdir} + DESTINATION ${LIBCXX_INSTALL_PATH}include/c++/v1/${dstdir} COMPONENT cxx-headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 90f6dcf6b..91e256331 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -204,7 +204,7 @@ else() endif() if(NOT LIBCXX_USING_INSTALLED_LLVM AND LLVM_BINARY_DIR) - set(output_dir ${LLVM_BINARY_DIR}/include/c++/v1) + set(output_dir ${LIBCXX_HEADER_DIR}/include/c++/v1) set(out_files) foreach(f ${files}) @@ -238,7 +238,7 @@ if (LIBCXX_INSTALL_HEADERS) foreach(file ${files}) get_filename_component(dir ${file} DIRECTORY) install(FILES ${file} - DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1/${dir} + DESTINATION ${LIBCXX_INSTALL_PATH}include/c++/v1/${dir} COMPONENT cxx-headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) @@ -247,7 +247,7 @@ if (LIBCXX_INSTALL_HEADERS) if (LIBCXX_NEEDS_SITE_CONFIG) # Install the generated header as __config. install(FILES ${LIBCXX_BINARY_DIR}/__generated_config - DESTINATION ${LIBCXX_INSTALL_PREFIX}include/c++/v1 + DESTINATION ${LIBCXX_INSTALL_PATH}include/c++/v1 PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ RENAME __config COMPONENT cxx-headers) -- GitLab From 92f1507ade33e207338edb0c61dc9ba4e7b24b19 Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha Date: Thu, 28 Jun 2018 18:35:35 +0000 Subject: [PATCH 004/495] [CMake] Rename cxx_headers back to cxx-headers. r334477 renamed the cxx-headers target to cxx_headers, but various pieces sort-of expect the target names to match the component (e.g., LLVM_DISTRIBUTION_COMPONENTS in the various bootstrap caches, which, via some magic foreign to me, seems to expect cxx-headers, install-cxx-headers, and install-cxx-headers-stripped to exist.) Revert back to cxx-headers. Differential Revision: https://reviews.llvm.org/D48701 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@335899 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/CMakeLists.txt | 8 ++++---- lib/CMakeLists.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 91e256331..6bd75915d 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -228,11 +228,11 @@ if(NOT LIBCXX_USING_INSTALLED_LLVM AND LLVM_BINARY_DIR) list(APPEND out_files ${dst}) endif() - add_custom_target(cxx_headers ALL DEPENDS ${out_files} ${LIBCXX_CXX_ABI_HEADER_TARGET}) + add_custom_target(cxx-headers ALL DEPENDS ${out_files} ${LIBCXX_CXX_ABI_HEADER_TARGET}) else() - add_custom_target(cxx_headers) + add_custom_target(cxx-headers) endif() -set_target_properties(cxx_headers PROPERTIES FOLDER "Misc") +set_target_properties(cxx-headers PROPERTIES FOLDER "Misc") if (LIBCXX_INSTALL_HEADERS) foreach(file ${files}) @@ -255,7 +255,7 @@ if (LIBCXX_INSTALL_HEADERS) if (NOT CMAKE_CONFIGURATION_TYPES) add_custom_target(install-cxx-headers - DEPENDS cxx_headers ${generated_config_deps} + DEPENDS cxx-headers ${generated_config_deps} COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cxx-headers -P "${CMAKE_BINARY_DIR}/cmake_install.cmake") diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index cba5aa9e8..d32f8fb8e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -286,7 +286,7 @@ if (LIBCXX_ENABLE_STATIC) endif() # Add a meta-target for both libraries. -add_custom_target(cxx DEPENDS cxx_headers ${LIBCXX_TARGETS}) +add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_TARGETS}) if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) file(GLOB LIBCXX_EXPERIMENTAL_SOURCES ../src/experimental/*.cpp) -- GitLab From b525131913352ac4c8c545ece73467e36d51f062 Mon Sep 17 00:00:00 2001 From: Pirama Arumuga Nainar Date: Thu, 28 Jun 2018 20:16:45 +0000 Subject: [PATCH 005/495] Configure ELAST for MinGW Summary: Use _LIBCPP_MSVCRT_LIKE while configuring ELAST, so MinGW gets the same configuration as MSVC. Reviewers: compnerd, srhines, danalbert, mstorsjo Subscribers: christof, ldionne, cfe-commits Differential Revision: https://reviews.llvm.org/D48731 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@335916 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/include/config_elast.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/config_elast.h b/src/include/config_elast.h index 4c4d853c2..c3cc19c22 100644 --- a/src/include/config_elast.h +++ b/src/include/config_elast.h @@ -12,7 +12,7 @@ #include <__config> -#if defined(_LIBCPP_MSVCRT) +#if defined(_LIBCPP_MSVCRT_LIKE) #include #else #include @@ -30,7 +30,7 @@ // No _LIBCPP_ELAST needed on Apple #elif defined(__sun__) #define _LIBCPP_ELAST ESTALE -#elif defined(_LIBCPP_MSVCRT) +#elif defined(_LIBCPP_MSVCRT_LIKE) #define _LIBCPP_ELAST (_sys_nerr - 1) #else // Warn here so that the person doing the libcxx port has an easier time: -- GitLab From 64c10d00c397691babc8fe82dd8dbe50d7b7bdf9 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 2 Jul 2018 18:41:15 +0000 Subject: [PATCH 006/495] Implement LWG 2946, 3075 and 3076. Reviewed as https://reviews.llvm.org/D48616 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336132 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/memory | 8 +- include/string | 395 +++++++++++++----- .../string.cons/copy_assignment.pass.cpp | 9 + .../string.cons/default_noexcept.pass.cpp | 9 +- .../string.cons/dtor_noexcept.pass.cpp | 9 +- .../implicit_deduction_guides.pass.cpp | 51 ++- .../string.cons/move_assign_noexcept.pass.cpp | 3 + .../string.cons/move_noexcept.pass.cpp | 9 +- .../string.cons/pointer_size_alloc.pass.cpp | 8 + .../string_view_deduction.fail.cpp | 41 ++ .../string_view_deduction.pass.cpp | 95 +++++ .../string_view_size_size_deduction.fail.cpp | 47 +++ .../string_view_size_size_deduction.pass.cpp | 99 +++++ .../string_append/string.pass.cpp | 9 + .../string_insert/size_string.pass.cpp | 9 + .../string_op_plus_equal/string.pass.cpp | 9 + .../string_replace/iter_iter_string.pass.cpp | 9 + .../string_replace/size_size_string.pass.cpp | 9 + .../string.special/swap_noexcept.pass.cpp | 3 +- .../string_compare/size_size_string.pass.cpp | 10 +- .../string.ops/string_compare/string.pass.cpp | 8 + .../string_size.pass.cpp | 8 + .../string_find.first.of/string_size.pass.cpp | 8 + .../string_size.pass.cpp | 8 + .../string_find.last.of/string_size.pass.cpp | 8 + .../string_find/string_size.pass.cpp | 8 + .../string_rfind/string_size.pass.cpp | 8 + www/cxx2a_status.html | 6 +- 28 files changed, 755 insertions(+), 148 deletions(-) create mode 100644 test/std/strings/basic.string/string.cons/string_view_deduction.fail.cpp create mode 100644 test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp create mode 100644 test/std/strings/basic.string/string.cons/string_view_size_size_deduction.fail.cpp create mode 100644 test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp diff --git a/include/memory b/include/memory index 021bd136a..31d4e4fac 100644 --- a/include/memory +++ b/include/memory @@ -5638,15 +5638,15 @@ struct __temp_value { }; #endif -#if _LIBCPP_STD_VER > 14 -template +template struct __is_allocator : false_type {}; template struct __is_allocator<_Alloc, - void_t().allocate(size_t{}))>> + typename __void_t::type, + typename __void_t().allocate(size_t(0)))>::type + > : true_type {}; -#endif _LIBCPP_END_NAMESPACE_STD diff --git a/include/string b/include/string index bfdd141cd..96d36f4f7 100644 --- a/include/string +++ b/include/string @@ -104,7 +104,8 @@ public: const Allocator& a = Allocator()); template basic_string(const T& t, size_type pos, size_type n, const Allocator& a = Allocator()); // C++17 - explicit basic_string(const basic_string_view sv, const Allocator& a = Allocator()); + template + explicit basic_string(const T& t, const Allocator& a = Allocator()); // C++17 basic_string(const value_type* s, const allocator_type& a = allocator_type()); basic_string(const value_type* s, size_type n, const allocator_type& a = allocator_type()); basic_string(size_type n, value_type c, const allocator_type& a = allocator_type()); @@ -120,7 +121,8 @@ public: operator basic_string_view() const noexcept; basic_string& operator=(const basic_string& str); - basic_string& operator=(basic_string_view sv); + template + basic_string& operator=(const T& t); // C++17 basic_string& operator=(basic_string&& str) noexcept( allocator_type::propagate_on_container_move_assignment::value || @@ -164,13 +166,15 @@ public: reference at(size_type n); basic_string& operator+=(const basic_string& str); - basic_string& operator+=(basic_string_view sv); + template + basic_string& operator+=(const T& t); // C++17 basic_string& operator+=(const value_type* s); basic_string& operator+=(value_type c); basic_string& operator+=(initializer_list); basic_string& append(const basic_string& str); - basic_string& append(basic_string_view sv); + template + basic_string& append(const T& t); // C++17 basic_string& append(const basic_string& str, size_type pos, size_type n=npos); //C++14 template basic_string& append(const T& t, size_type pos, size_type n=npos); // C++17 @@ -189,7 +193,8 @@ public: const_reference back() const; basic_string& assign(const basic_string& str); - basic_string& assign(basic_string_view sv); + template + basic_string& assign(const T& t); // C++17 basic_string& assign(basic_string&& str); basic_string& assign(const basic_string& str, size_type pos, size_type n=npos); // C++14 template @@ -202,7 +207,8 @@ public: basic_string& assign(initializer_list); basic_string& insert(size_type pos1, const basic_string& str); - basic_string& insert(size_type pos1, basic_string_view sv); + template + basic_string& insert(size_type pos1, const T& t); basic_string& insert(size_type pos1, const basic_string& str, size_type pos2, size_type n); template @@ -221,7 +227,8 @@ public: iterator erase(const_iterator first, const_iterator last); basic_string& replace(size_type pos1, size_type n1, const basic_string& str); - basic_string& replace(size_type pos1, size_type n1, basic_string_view sv); + template + basic_string& replace(size_type pos1, size_type n1, const T& t); // C++17 basic_string& replace(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2=npos); // C++14 template @@ -231,7 +238,8 @@ public: basic_string& replace(size_type pos, size_type n1, const value_type* s); basic_string& replace(size_type pos, size_type n1, size_type n2, value_type c); basic_string& replace(const_iterator i1, const_iterator i2, const basic_string& str); - basic_string& replace(const_iterator i1, const_iterator i2, basic_string_view sv); + template + basic_string& replace(const_iterator i1, const_iterator i2, const T& t); // C++17 basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s, size_type n); basic_string& replace(const_iterator i1, const_iterator i2, const value_type* s); basic_string& replace(const_iterator i1, const_iterator i2, size_type n, value_type c); @@ -253,45 +261,53 @@ public: allocator_type get_allocator() const noexcept; size_type find(const basic_string& str, size_type pos = 0) const noexcept; - size_type find(basic_string_view sv, size_type pos = 0) const noexcept; + template + size_type find(const T& t, size_type pos = 0) const; // C++17 size_type find(const value_type* s, size_type pos, size_type n) const noexcept; size_type find(const value_type* s, size_type pos = 0) const noexcept; size_type find(value_type c, size_type pos = 0) const noexcept; size_type rfind(const basic_string& str, size_type pos = npos) const noexcept; - size_type rfind(basic_string_view sv, size_type pos = npos) const noexcept; + template + size_type rfind(const T& t, size_type pos = npos) const; // C++17 size_type rfind(const value_type* s, size_type pos, size_type n) const noexcept; size_type rfind(const value_type* s, size_type pos = npos) const noexcept; size_type rfind(value_type c, size_type pos = npos) const noexcept; size_type find_first_of(const basic_string& str, size_type pos = 0) const noexcept; - size_type find_first_of(basic_string_view sv, size_type pos = 0) const noexcept; + template + size_type find_first_of(const T& t, size_type pos = 0) const; // C++17 size_type find_first_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_first_of(const value_type* s, size_type pos = 0) const noexcept; size_type find_first_of(value_type c, size_type pos = 0) const noexcept; size_type find_last_of(const basic_string& str, size_type pos = npos) const noexcept; - size_type find_last_of(basic_string_view sv, size_type pos = npos) const noexcept; + template + size_type find_last_of(const T& t, size_type pos = npos) const noexcept; // C++17 size_type find_last_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_last_of(const value_type* s, size_type pos = npos) const noexcept; size_type find_last_of(value_type c, size_type pos = npos) const noexcept; size_type find_first_not_of(const basic_string& str, size_type pos = 0) const noexcept; - size_type find_first_not_of(basic_string_view sv, size_type pos = 0) const noexcept; + template + size_type find_first_not_of(const T& t, size_type pos = 0) const; // C++17 size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_first_not_of(const value_type* s, size_type pos = 0) const noexcept; size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept; size_type find_last_not_of(const basic_string& str, size_type pos = npos) const noexcept; - size_type find_last_not_of(basic_string_view sv, size_type pos = npos) const noexcept; + template + size_type find_last_not_of(const T& t, size_type pos = npos) const; // C++17 size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const noexcept; size_type find_last_not_of(const value_type* s, size_type pos = npos) const noexcept; size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept; int compare(const basic_string& str) const noexcept; - int compare(basic_string_view sv) const noexcept; + template + int compare(const T& t) const noexcept; // C++17 int compare(size_type pos1, size_type n1, const basic_string& str) const; - int compare(size_type pos1, size_type n1, basic_string_view sv) const; + template + int compare(size_type pos1, size_type n1, const T& t) const; // C++17 int compare(size_type pos1, size_type n1, const basic_string& str, size_type pos2, size_type n2=npos) const; // C++14 template @@ -665,6 +681,7 @@ public: "traits_type::char_type must be the same type as CharT"); static_assert(( is_same::value), "Allocator::value_type must be same type as value_type"); + #if defined(_LIBCPP_RAW_ITERATORS) typedef pointer iterator; typedef const_pointer const_iterator; @@ -788,31 +805,45 @@ public: _LIBCPP_INLINE_VISIBILITY basic_string(basic_string&& __str, const allocator_type& __a); #endif // _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s); - _LIBCPP_INLINE_VISIBILITY - basic_string(const _CharT* __s, const _Allocator& __a); + + template ::value, nullptr_t>::type> + _LIBCPP_INLINE_VISIBILITY + basic_string(const _CharT* __s); + + template ::value, nullptr_t>::type> + _LIBCPP_INLINE_VISIBILITY + basic_string(const _CharT* __s, const _Allocator& __a); + _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s, size_type __n); _LIBCPP_INLINE_VISIBILITY basic_string(const _CharT* __s, size_type __n, const _Allocator& __a); _LIBCPP_INLINE_VISIBILITY basic_string(size_type __n, _CharT __c); - _LIBCPP_INLINE_VISIBILITY - basic_string(size_type __n, _CharT __c, const _Allocator& __a); + + template ::value, nullptr_t>::type> + _LIBCPP_INLINE_VISIBILITY + basic_string(size_type __n, _CharT __c, const _Allocator& __a); + basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Allocator& __a = _Allocator()); _LIBCPP_INLINE_VISIBILITY basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a = _Allocator()); - template + + template::value, void>::type> _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS basic_string(const _Tp& __t, size_type __pos, size_type __n, - const allocator_type& __a = allocator_type(), - typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type* = 0); - _LIBCPP_INLINE_VISIBILITY explicit - basic_string(__self_view __sv); - _LIBCPP_INLINE_VISIBILITY - basic_string(__self_view __sv, const _Allocator& __a); + const allocator_type& __a = allocator_type()); + + template::value, void>::type> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + explicit basic_string(const _Tp& __t); + + template::value, void>::type> + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + explicit basic_string(const _Tp& __t, const allocator_type& __a); + template _LIBCPP_INLINE_VISIBILITY basic_string(_InputIterator __first, _InputIterator __last); @@ -833,11 +864,10 @@ public: basic_string& operator=(const basic_string& __str); -#ifndef _LIBCPP_CXX03_LANG - template -#endif - _LIBCPP_INLINE_VISIBILITY - basic_string& operator=(__self_view __sv) {return assign(__sv);} + template ::value, void>::type> + basic_string& operator=(const _Tp& __t) + {__self_view __sv = __t; return assign(__sv);} + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_string& operator=(basic_string&& __str) @@ -927,7 +957,15 @@ public: reference at(size_type __n); _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(const basic_string& __str) {return append(__str);} - _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(__self_view __sv) {return append(__sv);} + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + basic_string& + >::type + operator+=(const _Tp& __t) {__self_view __sv = __t; return append(__sv);} _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(const value_type* __s) {return append(__s);} _LIBCPP_INLINE_VISIBILITY basic_string& operator+=(value_type __c) {push_back(__c); return *this;} #ifndef _LIBCPP_CXX03_LANG @@ -936,9 +974,17 @@ public: _LIBCPP_INLINE_VISIBILITY basic_string& append(const basic_string& __str); - _LIBCPP_INLINE_VISIBILITY - basic_string& append(__self_view __sv) { return append(__sv.data(), __sv.size()); } + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + basic_string& + >::type + append(const _Tp& __t) { __self_view __sv = __t; return append(__sv.data(), __sv.size()); } basic_string& append(const basic_string& __str, size_type __pos, size_type __n=npos); + template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if @@ -993,8 +1039,14 @@ public: _LIBCPP_INLINE_VISIBILITY reference back(); _LIBCPP_INLINE_VISIBILITY const_reference back() const; - _LIBCPP_INLINE_VISIBILITY - basic_string& assign(__self_view __sv) { return assign(__sv.data(), __sv.size()); } + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + basic_string& + >::type + assign(const _Tp & __t) { __self_view __sv = __t; return assign(__sv.data(), __sv.size()); } _LIBCPP_INLINE_VISIBILITY basic_string& assign(const basic_string& __str) { return *this = __str; } #ifndef _LIBCPP_CXX03_LANG @@ -1040,8 +1092,17 @@ public: _LIBCPP_INLINE_VISIBILITY basic_string& insert(size_type __pos1, const basic_string& __str); - _LIBCPP_INLINE_VISIBILITY - basic_string& insert(size_type __pos1, __self_view __sv) { return insert(__pos1, __sv.data(), __sv.size()); } + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + basic_string& + >::type + insert(size_type __pos1, const _Tp& __t) + { __self_view __sv = __t; return insert(__pos1, __sv.data(), __sv.size()); } + template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS typename enable_if @@ -1089,8 +1150,15 @@ public: _LIBCPP_INLINE_VISIBILITY basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str); - _LIBCPP_INLINE_VISIBILITY - basic_string& replace(size_type __pos1, size_type __n1, __self_view __sv) { return replace(__pos1, __n1, __sv.data(), __sv.size()); } + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + basic_string& + >::type + replace(size_type __pos1, size_type __n1, const _Tp& __t) { __self_view __sv = __t; return replace(__pos1, __n1, __sv.data(), __sv.size()); } basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2=npos); template _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS @@ -1105,8 +1173,16 @@ public: basic_string& replace(size_type __pos, size_type __n1, size_type __n2, value_type __c); _LIBCPP_INLINE_VISIBILITY basic_string& replace(const_iterator __i1, const_iterator __i2, const basic_string& __str); - _LIBCPP_INLINE_VISIBILITY - basic_string& replace(const_iterator __i1, const_iterator __i2, __self_view __sv) { return replace(__i1 - begin(), __i2 - __i1, __sv); } + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + basic_string& + >::type + replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) { __self_view __sv = __t; return replace(__i1 - begin(), __i2 - __i1, __sv); } + _LIBCPP_INLINE_VISIBILITY basic_string& replace(const_iterator __i1, const_iterator __i2, const value_type* __s, size_type __n); _LIBCPP_INLINE_VISIBILITY @@ -1154,8 +1230,15 @@ public: _LIBCPP_INLINE_VISIBILITY size_type find(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY - size_type find(__self_view __sv, size_type __pos = 0) const _NOEXCEPT; + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + size_type + >::type + find(const _Tp& __t, size_type __pos = 0) const; size_type find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; @@ -1163,8 +1246,15 @@ public: _LIBCPP_INLINE_VISIBILITY size_type rfind(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY - size_type rfind(__self_view __sv, size_type __pos = npos) const _NOEXCEPT; + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + size_type + >::type + rfind(const _Tp& __t, size_type __pos = npos) const; size_type rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type rfind(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; @@ -1172,8 +1262,15 @@ public: _LIBCPP_INLINE_VISIBILITY size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY - size_type find_first_of(__self_view __sv, size_type __pos = 0) const _NOEXCEPT; + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + size_type + >::type + find_first_of(const _Tp& __t, size_type __pos = 0) const; size_type find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; @@ -1182,8 +1279,15 @@ public: _LIBCPP_INLINE_VISIBILITY size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY - size_type find_last_of(__self_view __sv, size_type __pos = npos) const _NOEXCEPT; + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + size_type + >::type + find_last_of(const _Tp& __t, size_type __pos = npos) const; size_type find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; @@ -1192,8 +1296,15 @@ public: _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY - size_type find_first_not_of(__self_view __sv, size_type __pos = 0) const _NOEXCEPT; + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + size_type + >::type + find_first_not_of(const _Tp &__t, size_type __pos = 0) const; size_type find_first_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_first_not_of(const value_type* __s, size_type __pos = 0) const _NOEXCEPT; @@ -1202,8 +1313,15 @@ public: _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY - size_type find_last_not_of(__self_view __sv, size_type __pos = npos) const _NOEXCEPT; + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + size_type + >::type + find_last_not_of(const _Tp& __t, size_type __pos = npos) const; size_type find_last_not_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY size_type find_last_not_of(const value_type* __s, size_type __pos = npos) const _NOEXCEPT; @@ -1212,13 +1330,29 @@ public: _LIBCPP_INLINE_VISIBILITY int compare(const basic_string& __str) const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY - int compare(__self_view __sv) const _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY - int compare(size_type __pos1, size_type __n1, __self_view __sv) const; + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + int + >::type + compare(const _Tp &__t) const; + + template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS + typename enable_if + < + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + int + >::type + compare(size_type __pos1, size_type __n1, const _Tp& __t) const; + _LIBCPP_INLINE_VISIBILITY int compare(size_type __pos1, size_type __n1, const basic_string& __str) const; int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2=npos) const; + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -1503,6 +1637,23 @@ template basic_string(_InputIterator, _InputIterator, _Allocator = _Allocator()) -> basic_string<_CharT, char_traits<_CharT>, _Allocator>; + +template, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type + > +explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator()) + -> basic_string<_CharT, _Traits, _Allocator>; + +template, + class = typename enable_if<__is_allocator<_Allocator>::value, void>::type, + class _Sz = typename allocator_traits<_Allocator>::size_type + > +basic_string(basic_string_view<_CharT, _Traits>, _Sz, _Sz, const _Allocator& = _Allocator()) + -> basic_string<_CharT, _Traits, _Allocator>; #endif @@ -1623,7 +1774,7 @@ basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_ty } template -inline _LIBCPP_INLINE_VISIBILITY +template basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s) { _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr"); @@ -1634,7 +1785,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s) } template -inline _LIBCPP_INLINE_VISIBILITY +template basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const _Allocator& __a) : __r_(__second_tag(), __a) { @@ -1771,7 +1922,7 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __ } template -inline _LIBCPP_INLINE_VISIBILITY +template basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, _CharT __c, const _Allocator& __a) : __r_(__second_tag(), __a) { @@ -1812,13 +1963,13 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __st } template -template +template basic_string<_CharT, _Traits, _Allocator>::basic_string( - const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a, - typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type *) + const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a) : __r_(__second_tag(), __a) { - __self_view __sv = __self_view(__t).substr(__pos, __n); + __self_view __sv0 = __t; + __self_view __sv = __sv0.substr(__pos, __n); __init(__sv.data(), __sv.size()); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); @@ -1826,9 +1977,10 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string( } template -inline _LIBCPP_INLINE_VISIBILITY -basic_string<_CharT, _Traits, _Allocator>::basic_string(__self_view __sv) +template +basic_string<_CharT, _Traits, _Allocator>::basic_string(const _Tp & __t) { + __self_view __sv = __t; __init(__sv.data(), __sv.size()); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); @@ -1836,10 +1988,11 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(__self_view __sv) } template -inline _LIBCPP_INLINE_VISIBILITY -basic_string<_CharT, _Traits, _Allocator>::basic_string(__self_view __sv, const _Allocator& __a) +template +basic_string<_CharT, _Traits, _Allocator>::basic_string(const _Tp & __t, const _Allocator& __a) : __r_(__second_tag(), __a) { + __self_view __sv = __t; __init(__sv.data(), __sv.size()); #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__insert_c(this); @@ -3149,11 +3302,16 @@ basic_string<_CharT, _Traits, _Allocator>::find(const basic_string& __str, } template -inline _LIBCPP_INLINE_VISIBILITY -typename basic_string<_CharT, _Traits, _Allocator>::size_type -basic_string<_CharT, _Traits, _Allocator>::find(__self_view __sv, - size_type __pos) const _NOEXCEPT +template +typename enable_if +< + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + typename basic_string<_CharT, _Traits, _Allocator>::size_type +>::type +basic_string<_CharT, _Traits, _Allocator>::find(const _Tp &__t, + size_type __pos) const { + __self_view __sv = __t; return __str_find (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3202,11 +3360,16 @@ basic_string<_CharT, _Traits, _Allocator>::rfind(const basic_string& __str, } template -inline _LIBCPP_INLINE_VISIBILITY -typename basic_string<_CharT, _Traits, _Allocator>::size_type -basic_string<_CharT, _Traits, _Allocator>::rfind(__self_view __sv, - size_type __pos) const _NOEXCEPT +template +typename enable_if +< + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + typename basic_string<_CharT, _Traits, _Allocator>::size_type +>::type +basic_string<_CharT, _Traits, _Allocator>::rfind(const _Tp& __t, + size_type __pos) const { + __self_view __sv = __t; return __str_rfind (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3255,11 +3418,16 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const basic_string& __s } template -inline _LIBCPP_INLINE_VISIBILITY -typename basic_string<_CharT, _Traits, _Allocator>::size_type -basic_string<_CharT, _Traits, _Allocator>::find_first_of(__self_view __sv, - size_type __pos) const _NOEXCEPT +template +typename enable_if +< + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + typename basic_string<_CharT, _Traits, _Allocator>::size_type +>::type +basic_string<_CharT, _Traits, _Allocator>::find_first_of(const _Tp& __t, + size_type __pos) const { + __self_view __sv = __t; return __str_find_first_of (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3308,11 +3476,16 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const basic_string& __st } template -inline _LIBCPP_INLINE_VISIBILITY -typename basic_string<_CharT, _Traits, _Allocator>::size_type -basic_string<_CharT, _Traits, _Allocator>::find_last_of(__self_view __sv, - size_type __pos) const _NOEXCEPT +template +typename enable_if +< + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + typename basic_string<_CharT, _Traits, _Allocator>::size_type +>::type +basic_string<_CharT, _Traits, _Allocator>::find_last_of(const _Tp& __t, + size_type __pos) const { + __self_view __sv = __t; return __str_find_last_of (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3361,11 +3534,16 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const basic_string& } template -inline _LIBCPP_INLINE_VISIBILITY -typename basic_string<_CharT, _Traits, _Allocator>::size_type -basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(__self_view __sv, - size_type __pos) const _NOEXCEPT +template +typename enable_if +< + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + typename basic_string<_CharT, _Traits, _Allocator>::size_type +>::type +basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const _Tp& __t, + size_type __pos) const { + __self_view __sv = __t; return __str_find_first_not_of (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3415,11 +3593,16 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const basic_string& } template -inline _LIBCPP_INLINE_VISIBILITY -typename basic_string<_CharT, _Traits, _Allocator>::size_type -basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(__self_view __sv, - size_type __pos) const _NOEXCEPT +template +typename enable_if +< + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + typename basic_string<_CharT, _Traits, _Allocator>::size_type +>::type +basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const _Tp& __t, + size_type __pos) const { + __self_view __sv = __t; return __str_find_last_not_of (data(), size(), __sv.data(), __pos, __sv.size()); } @@ -3448,10 +3631,15 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(value_type __c, // compare template -inline _LIBCPP_INLINE_VISIBILITY -int -basic_string<_CharT, _Traits, _Allocator>::compare(__self_view __sv) const _NOEXCEPT +template +typename enable_if +< + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + int +>::type +basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const { + __self_view __sv = __t; size_t __lhs_sz = size(); size_t __rhs_sz = __sv.size(); int __result = traits_type::compare(data(), __sv.data(), @@ -3497,12 +3685,17 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, } template -inline _LIBCPP_INLINE_VISIBILITY -int +template +typename enable_if +< + __can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, + int +>::type basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, - __self_view __sv) const + const _Tp& __t) const { + __self_view __sv = __t; return compare(__pos1, __n1, __sv.data(), __sv.size()); } diff --git a/test/std/strings/basic.string/string.cons/copy_assignment.pass.cpp b/test/std/strings/basic.string/string.cons/copy_assignment.pass.cpp index b1e9108e9..34d5f306a 100644 --- a/test/std/strings/basic.string/string.cons/copy_assignment.pass.cpp +++ b/test/std/strings/basic.string/string.cons/copy_assignment.pass.cpp @@ -68,4 +68,13 @@ int main() S("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz")); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s; + s = {"abc", 1}; + assert(s.size() == 1); + assert(s == "a"); + } +#endif } diff --git a/test/std/strings/basic.string/string.cons/default_noexcept.pass.cpp b/test/std/strings/basic.string/string.cons/default_noexcept.pass.cpp index 87698ec55..a995a51ee 100644 --- a/test/std/strings/basic.string/string.cons/default_noexcept.pass.cpp +++ b/test/std/strings/basic.string/string.cons/default_noexcept.pass.cpp @@ -22,13 +22,6 @@ #include "test_macros.h" #include "test_allocator.h" -template -struct some_alloc -{ - typedef T value_type; - some_alloc(const some_alloc&); -}; - int main() { { @@ -40,7 +33,7 @@ int main() static_assert(std::is_nothrow_default_constructible::value, ""); } { - typedef std::basic_string, some_alloc> C; + typedef std::basic_string, limited_allocator> C; static_assert(!std::is_nothrow_default_constructible::value, ""); } } diff --git a/test/std/strings/basic.string/string.cons/dtor_noexcept.pass.cpp b/test/std/strings/basic.string/string.cons/dtor_noexcept.pass.cpp index f4ff0645a..a4de566a4 100644 --- a/test/std/strings/basic.string/string.cons/dtor_noexcept.pass.cpp +++ b/test/std/strings/basic.string/string.cons/dtor_noexcept.pass.cpp @@ -20,11 +20,12 @@ #include "test_allocator.h" template -struct some_alloc +struct throwing_alloc { typedef T value_type; - some_alloc(const some_alloc&); - ~some_alloc() noexcept(false); + throwing_alloc(const throwing_alloc&); + T *allocate(size_t); + ~throwing_alloc() noexcept(false); }; // Test that it's possible to take the address of basic_string's destructors @@ -44,7 +45,7 @@ int main() } #if defined(_LIBCPP_VERSION) { - typedef std::basic_string, some_alloc> C; + typedef std::basic_string, throwing_alloc> C; static_assert(!std::is_nothrow_destructible::value, ""); } #endif // _LIBCPP_VERSION diff --git a/test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp b/test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp index 0fbd663db..3665e23a7 100644 --- a/test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp +++ b/test/std/strings/basic.string/string.cons/implicit_deduction_guides.pass.cpp @@ -36,7 +36,7 @@ using BStr = std::basic_string, Alloc>; // (2) basic_string(A const&) - BROKEN // (3) basic_string(size_type, CharT, const A& = A()) // (4) basic_string(BS const&, size_type, A const& = A()) -// (5) basic_string(BS const&, size_type, size_type, A const& = A()) - PARTIALLY BROKEN +// (5) basic_string(BS const&, size_type, size_type, A const& = A()) // (6) basic_string(const CharT*, size_type, A const& = A()) // (7) basic_string(const CharT*, A const& = A()) // (8) basic_string(InputIt, InputIt, A const& = A()) - BROKEN @@ -46,7 +46,7 @@ using BStr = std::basic_string, Alloc>; // (12) basic_string(BS&&, A const&) // (13) basic_string(initializer_list, A const& = A()) // (14) basic_string(BSV, A const& = A()) -// (15) basic_string(const T&, size_type, size_type, A const& = A()) - BROKEN +// (15) basic_string(const T&, size_type, size_type, A const& = A()) int main() { using TestSizeT = test_allocator::size_type; @@ -106,7 +106,6 @@ int main() assert(w == L"def"); } { // Testing (5) w/o allocator -#if 0 // FIXME: This doesn't work const std::string sin("abc"); std::basic_string s(sin, (size_t)1, (size_t)3); ASSERT_SAME_TYPE(decltype(s), std::string); @@ -119,7 +118,6 @@ int main() std::basic_string w(win, (TestSizeT)2, (TestSizeT)3); ASSERT_SAME_TYPE(decltype(w), WStr); assert(w == L"cde"); -#endif } { // Testing (5) w/ allocator const std::string sin("abc"); @@ -178,20 +176,19 @@ int main() assert(w == L"abcdef"); } { // (8) w/o allocator - // This overload isn't compatible with implicit deduction guides as - // specified in the standard. - // FIXME: Propose adding an explicit guide to the standard? - } - { // (8) w/ allocator - // This overload isn't compatible with implicit deduction guides as - // specified in the standard. - // FIXME: Propose adding an explicit guide to the standard? -#if 0 using It = input_iterator; const char* input = "abcdef"; std::basic_string s(It(input), It(input + 3), std::allocator{}); ASSERT_SAME_TYPE(decltype(s), std::string); -#endif + assert(s == "abc"); + } + { // (8) w/ allocator + using ExpectW = std::basic_string, test_allocator>; + using It = input_iterator; + const wchar_t* input = L"abcdef"; + std::basic_string s(It(input), It(input + 3), test_allocator{}); + ASSERT_SAME_TYPE(decltype(s), ExpectW); + assert(s == L"abc"); } { // Testing (9) const std::string sin("abc"); @@ -293,8 +290,28 @@ int main() ASSERT_SAME_TYPE(decltype(w), ExpectW); assert(w == L"abcdef"); } - { // Testing (15) - // This overload isn't compatible with implicit deduction guides as - // specified in the standard. + { // Testing (15) w/o allocator + std::string s0("abc"); + std::basic_string s(s0, 1, 1); + ASSERT_SAME_TYPE(decltype(s), std::string); + assert(s == "b"); + + std::wstring w0(L"abcdef"); + std::basic_string w(w0, 2, 2); + ASSERT_SAME_TYPE(decltype(w), std::wstring); + assert(w == L"cd"); + } + { // Testing (15) w/ allocator + using ExpectS = std::basic_string, test_allocator>; + ExpectS s0("abc"); + std::basic_string s(s0, 1, 1, test_allocator{4}); + ASSERT_SAME_TYPE(decltype(s), ExpectS); + assert(s == "b"); + + using ExpectW = std::basic_string, test_allocator>; + ExpectW w0(L"abcdef"); + std::basic_string w(w0, 2, 2, test_allocator{6}); + ASSERT_SAME_TYPE(decltype(w), ExpectW); + assert(w == L"cd"); } } diff --git a/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp b/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp index 072054342..ad9ed36d3 100644 --- a/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp +++ b/test/std/strings/basic.string/string.cons/move_assign_noexcept.pass.cpp @@ -32,6 +32,7 @@ struct some_alloc { typedef T value_type; some_alloc(const some_alloc&); + T *allocate(size_t); }; template @@ -41,6 +42,7 @@ struct some_alloc2 some_alloc2() {} some_alloc2(const some_alloc2&); + T *allocate(size_t); void deallocate(void*, unsigned) {} typedef std::false_type propagate_on_container_move_assignment; @@ -54,6 +56,7 @@ struct some_alloc3 some_alloc3() {} some_alloc3(const some_alloc3&); + T *allocate(size_t); void deallocate(void*, unsigned) {} typedef std::false_type propagate_on_container_move_assignment; diff --git a/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp b/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp index 9a7c65ca2..e0e4a4ff3 100644 --- a/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp +++ b/test/std/strings/basic.string/string.cons/move_noexcept.pass.cpp @@ -22,13 +22,6 @@ #include "test_macros.h" #include "test_allocator.h" -template -struct some_alloc -{ - typedef T value_type; - some_alloc(const some_alloc&); -}; - int main() { { @@ -40,7 +33,7 @@ int main() static_assert(std::is_nothrow_move_constructible::value, ""); } { - typedef std::basic_string, some_alloc> C; + typedef std::basic_string, limited_allocator> C; #if TEST_STD_VER <= 14 static_assert(!std::is_nothrow_move_constructible::value, ""); #else diff --git a/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp b/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp index 3c75a700e..6d660fd10 100644 --- a/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp +++ b/test/std/strings/basic.string/string.cons/pointer_size_alloc.pass.cpp @@ -83,4 +83,12 @@ int main() test("123456798012345679801234567980123456798012345679801234567980", 60, A()); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s({"abc", 1}); + assert(s.size() == 1); + assert(s == "a"); + } +#endif } diff --git a/test/std/strings/basic.string/string.cons/string_view_deduction.fail.cpp b/test/std/strings/basic.string/string.cons/string_view_deduction.fail.cpp new file mode 100644 index 000000000..b2fece8da --- /dev/null +++ b/test/std/strings/basic.string/string.cons/string_view_deduction.fail.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// XFAIL: libcpp-no-deduction-guides + +// template +// basic_string(InputIterator begin, InputIterator end, +// const Allocator& a = Allocator()); + +// template +// > +// basic_string(basic_string_view, const Allocator& = Allocator()) +// -> basic_string; +// +// The deduction guide shall not participate in overload resolution if Allocator +// is a type that does not qualify as an allocator. + + +#include +#include +#include +#include +#include + +int main() +{ + { + std::string_view sv = "12345678901234"; + std::basic_string s1{sv, 23}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}} + } +} diff --git a/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp b/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp new file mode 100644 index 000000000..df1e99e01 --- /dev/null +++ b/test/std/strings/basic.string/string.cons/string_view_deduction.pass.cpp @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// XFAIL: libcpp-no-deduction-guides + +// template +// basic_string(InputIterator begin, InputIterator end, +// const Allocator& a = Allocator()); + +// template +// > +// basic_string(basic_string_view, const Allocator& = Allocator()) +// -> basic_string; +// +// The deduction guide shall not participate in overload resolution if Allocator +// is a type that does not qualify as an allocator. + + +#include +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "test_allocator.h" +#include "../input_iterator.h" +#include "min_allocator.h" + +int main() +{ + { + std::string_view sv = "12345678901234"; + std::basic_string s1(sv); + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == sv.size()); + assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0); + } + + { + std::string_view sv = "12345678901234"; + std::basic_string s1{sv, std::allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == sv.size()); + assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0); + } + { + std::wstring_view sv = L"12345678901234"; + std::basic_string s1{sv, test_allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == sv.size()); + assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0); + } + { + std::u16string_view sv = u"12345678901234"; + std::basic_string s1{sv, min_allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == sv.size()); + assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0); + } + { + std::u32string_view sv = U"12345678901234"; + std::basic_string s1{sv, explicit_allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == sv.size()); + assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0); + } +} diff --git a/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.fail.cpp b/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.fail.cpp new file mode 100644 index 000000000..f79e43f6a --- /dev/null +++ b/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.fail.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// XFAIL: libcpp-no-deduction-guides + +// template +// basic_string(InputIterator begin, InputIterator end, +// const Allocator& a = Allocator()); + +// template +// > +// basic_string(basic_string_view, +// typename see below::size_type, +// typename see below::size_type, +// const Allocator& = Allocator()) +// -> basic_string; +// +// A size_type parameter type in a basic_string deduction guide refers to the size_type +// member type of the type deduced by the deduction guide. +// +// The deduction guide shall not participate in overload resolution if Allocator +// is a type that does not qualify as an allocator. + + +#include +#include +#include +#include +#include + +int main() +{ + { + std::string_view sv = "12345678901234"; + std::basic_string s1{sv, 0, 4, 23}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'basic_string'}} + } +} diff --git a/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp b/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp new file mode 100644 index 000000000..d9561d22b --- /dev/null +++ b/test/std/strings/basic.string/string.cons/string_view_size_size_deduction.pass.cpp @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// +// UNSUPPORTED: c++98, c++03, c++11, c++14 +// XFAIL: libcpp-no-deduction-guides + +// template +// basic_string(InputIterator begin, InputIterator end, +// const Allocator& a = Allocator()); + +// template +// > +// basic_string(basic_string_view, +// typename see below::size_type, +// typename see below::size_type, +// const Allocator& = Allocator()) +// -> basic_string; +// +// A size_type parameter type in a basic_string deduction guide refers to the size_type +// member type of the type deduced by the deduction guide. +// +// The deduction guide shall not participate in overload resolution if Allocator +// is a type that does not qualify as an allocator. + + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "test_allocator.h" +#include "../input_iterator.h" +#include "min_allocator.h" + +int main() +{ + { + std::string_view sv = "12345678901234"; + std::basic_string s1{sv, 0, 4}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == 4); + assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0); + } + + { + std::string_view sv = "12345678901234"; + std::basic_string s1{sv, 0, 4, std::allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == 4); + assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0); + } + { + std::wstring_view sv = L"12345678901234"; + std::basic_string s1{sv, 0, 4, test_allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == 4); + assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0); + } + { + std::u16string_view sv = u"12345678901234"; + std::basic_string s1{sv, 0, 4, min_allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == 4); + assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0); + } + { + std::u32string_view sv = U"12345678901234"; + std::basic_string s1{sv, 0, 4, explicit_allocator{}}; + using S = decltype(s1); // what type did we get? + static_assert(std::is_same_v, ""); + static_assert(std::is_same_v>, ""); + static_assert(std::is_same_v>, ""); + assert(s1.size() == 4); + assert(s1.compare(0, s1.size(), sv.data(), s1.size()) == 0); + } +} diff --git a/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp index b58ed6328..b3704268a 100644 --- a/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_append/string.pass.cpp @@ -77,4 +77,13 @@ int main() S("1234567890123456789012345678901234567890")); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s; + s.append({"abc", 1}); + assert(s.size() == 1); + assert(s == "a"); + } +#endif } diff --git a/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp index e7c5ecdc9..4c3a87248 100644 --- a/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_insert/size_string.pass.cpp @@ -218,4 +218,13 @@ int main() test(S("abcdefghijklmnopqrst"), 21, S("12345678901234567890"), S("can't happen")); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s; + s.insert(0, {"abc", 1}); + assert(s.size() == 1); + assert(s == "a"); + } +#endif } diff --git a/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp index 1064855c1..bbe385015 100644 --- a/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_op_plus_equal/string.pass.cpp @@ -77,4 +77,13 @@ int main() S("1234567890123456789012345678901234567890")); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s; + s += {"abc", 1}; + assert(s.size() == 1); + assert(s == "a"); + } +#endif } diff --git a/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp index 190e10d5c..f5f31254e 100644 --- a/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp @@ -281,4 +281,13 @@ int main() test2(); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s = " "; + s.replace(s.cbegin(), s.cend(), {"abc", 1}); + assert(s.size() == 1); + assert(s == "a"); + } +#endif } diff --git a/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp index 612e1e200..88982e098 100644 --- a/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp +++ b/test/std/strings/basic.string/string.modifiers/string_replace/size_size_string.pass.cpp @@ -379,4 +379,13 @@ int main() test2(); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s = " "; + s.replace(0, 1, {"abc", 1}); + assert(s.size() == 1); + assert(s == "a"); + } +#endif } diff --git a/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp b/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp index 73727198f..c8b784c24 100644 --- a/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp +++ b/test/std/strings/basic.string/string.nonmembers/string.special/swap_noexcept.pass.cpp @@ -35,8 +35,8 @@ struct some_alloc some_alloc() {} some_alloc(const some_alloc&); + T *allocate(size_t); void deallocate(void*, unsigned) {} - typedef std::true_type propagate_on_container_swap; }; @@ -47,6 +47,7 @@ struct some_alloc2 some_alloc2() {} some_alloc2(const some_alloc2&); + T *allocate(size_t); void deallocate(void*, unsigned) {} typedef std::false_type propagate_on_container_swap; diff --git a/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp b/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp index 0ddbf2e2f..be730cbc1 100644 --- a/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp +++ b/test/std/strings/basic.string/string.ops/string_compare/size_size_string.pass.cpp @@ -15,9 +15,8 @@ #include #include -#include "min_allocator.h" - #include "test_macros.h" +#include "min_allocator.h" int sign(int x) { @@ -378,4 +377,11 @@ int main() test2(); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s = " !"; + assert(s.compare(0, 1, {"abc", 1}) < 0); + } +#endif } diff --git a/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp b/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp index 3f6c169d2..80d579e30 100644 --- a/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp +++ b/test/std/strings/basic.string/string.ops/string_compare/string.pass.cpp @@ -14,6 +14,7 @@ #include #include +#include "test_macros.h" #include "min_allocator.h" int sign(int x) @@ -74,4 +75,11 @@ int main() test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrst"), 0); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s = " !"; + assert(s.compare({"abc", 1}) < 0); + } +#endif } diff --git a/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp b/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp index b7df34617..4ce343351 100644 --- a/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp +++ b/test/std/strings/basic.string/string.ops/string_find.first.not.of/string_size.pass.cpp @@ -14,6 +14,7 @@ #include #include +#include "test_macros.h" #include "min_allocator.h" template @@ -154,4 +155,11 @@ int main() test1(); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s = " !"; + assert(s.find_first_not_of({"abc", 1}) == 0); + } +#endif } diff --git a/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp b/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp index 765d1603a..105c2a6db 100644 --- a/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp +++ b/test/std/strings/basic.string/string.ops/string_find.first.of/string_size.pass.cpp @@ -14,6 +14,7 @@ #include #include +#include "test_macros.h" #include "min_allocator.h" template @@ -154,4 +155,11 @@ int main() test1(); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s = " !"; + assert(s.find_first_of({"abc", 1}) == std::string::npos); + } +#endif } diff --git a/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp b/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp index f3377596a..57fab60e7 100644 --- a/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp +++ b/test/std/strings/basic.string/string.ops/string_find.last.not.of/string_size.pass.cpp @@ -14,6 +14,7 @@ #include #include +#include "test_macros.h" #include "min_allocator.h" template @@ -154,4 +155,11 @@ int main() test1(); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s = " !"; + assert(s.find_last_not_of({"abc", 1}) == s.size() - 1); + } +#endif } diff --git a/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp b/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp index 5cb2df7c6..b6b5b8f12 100644 --- a/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp +++ b/test/std/strings/basic.string/string.ops/string_find.last.of/string_size.pass.cpp @@ -14,6 +14,7 @@ #include #include +#include "test_macros.h" #include "min_allocator.h" template @@ -154,4 +155,11 @@ int main() test1(); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s = " !"; + assert(s.find_last_of({"abc", 1}) == std::string::npos); + } +#endif } diff --git a/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp b/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp index e519a7943..769b51c8d 100644 --- a/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp +++ b/test/std/strings/basic.string/string.ops/string_find/string_size.pass.cpp @@ -14,6 +14,7 @@ #include #include +#include "test_macros.h" #include "min_allocator.h" template @@ -154,4 +155,11 @@ int main() test1(); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s = " !"; + assert(s.find({"abc", 1}) == std::string::npos); + } +#endif } diff --git a/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp b/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp index ef571c284..d7908ad85 100644 --- a/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp +++ b/test/std/strings/basic.string/string.ops/string_rfind/string_size.pass.cpp @@ -14,6 +14,7 @@ #include #include +#include "test_macros.h" #include "min_allocator.h" template @@ -154,4 +155,11 @@ int main() test1(); } #endif + +#if TEST_STD_VER > 3 + { // LWG 2946 + std::string s = " !"; + assert(s.rfind({"abc", 1}) == std::string::npos); + } +#endif } diff --git a/www/cxx2a_status.html b/www/cxx2a_status.html index ed512ec1c..9f195c35d 100644 --- a/www/cxx2a_status.html +++ b/www/cxx2a_status.html @@ -173,7 +173,7 @@ 2843Unclear behavior of std::pmr::memory_resource::do_allocate()Jacksonville 2849Why does !is_regular_file(from) cause copy_file to report a "file already exists" error?JacksonvilleNothing to do 2851std::filesystem enum classes are now underspecifiedJacksonvilleNothing to do - 2946LWG 2758's resolution missed further correctionsJacksonville + 2946LWG 2758's resolution missed further correctionsJacksonvilleComplete 2969polymorphic_allocator::construct() shouldn't pass resource()Jacksonville 2975Missing case for pair construction in scoped and polymorphic allocatorsJacksonville 2989path's stream insertion operator lets you insert everything under the sunJacksonvilleCompleted @@ -200,7 +200,7 @@ 3045atomic<floating-point> doesn't have value_type or difference_typeJacksonville 3048transform_reduce(exec, first1, last1, first2, init) discards execution policyJacksonville 3051Floating point classifications were inadvertently changed in P0175JacksonvilleNothing to do - 3075basic_string needs deduction guides from basic_string_viewJacksonville + 3075basic_string needs deduction guides from basic_string_viewJacksonvilleComplete 2139What is a user-defined type?Rapperswil @@ -210,7 +210,7 @@ 3067recursive_directory_iterator::pop must invalidateRapperswilNothing to do 3071[networking.ts] read_until still refers to "input sequence"RapperswilNothing to do 3074Non-member functions for valarray should only deduce from the valarrayRapperswil - 3076basic_string CTAD ambiguityRapperswil + 3076basic_string CTAD ambiguityRapperswilComplete 3079LWG 2935 forgot to fix the existing_p overloads of create_directoryRapperswil 3080Floating point from_chars pattern specification breaks round-trippingRapperswil 3083What should ios::iword(-1) do?RapperswilNothing to do -- GitLab From 03295feea204818d6057f29030e7268734ca9412 Mon Sep 17 00:00:00 2001 From: Pirama Arumuga Nainar Date: Mon, 2 Jul 2018 20:11:15 +0000 Subject: [PATCH 007/495] [Win32] Overload ==, != for locale_t and long long Summary: _is_chartype_l (needed for isxdigit_l) in MinGW compares locale_t and NULL. NULL is 'long long' for 64-bit, and this results in ambiguous overloads when compiled with Clang. Define a concrete overload for the operators to fix the ambiguity. Reviewers: mstorsjo, EricWF, srhines, danalbert Subscribers: christof, cfe-commits, ldionne Differential Revision: https://reviews.llvm.org/D48749 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336141 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/support/win32/locale_win32.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/support/win32/locale_win32.h b/include/support/win32/locale_win32.h index aebfff22e..68682c962 100644 --- a/include/support/win32/locale_win32.h +++ b/include/support/win32/locale_win32.h @@ -46,6 +46,10 @@ public: return __left.__locale == nullptr && __right == 0; } + friend bool operator==(const locale_t& __left, long long __right) { + return __left.__locale == nullptr && __right == 0; + } + friend bool operator==(const locale_t& __left, std::nullptr_t) { return __left.__locale == nullptr; } @@ -66,6 +70,10 @@ public: return !(__left == __right); } + friend bool operator!=(const locale_t& __left, long long __right) { + return !(__left == __right); + } + friend bool operator!=(const locale_t& __left, std::nullptr_t __right) { return !(__left == __right); } -- GitLab From 8deb2dd30a23e2772cc76d3e2007f1d0cf83bf85 Mon Sep 17 00:00:00 2001 From: Zhihao Yuan Date: Tue, 3 Jul 2018 03:25:10 +0000 Subject: [PATCH 008/495] [libc++] Lift std::errc into a separated header Summary: This is needed to implement ``, otherwise `` would need to include ``, which pulls in `` -- a header which the `` proposal intends to keep away from. Reviewers: mclow.lists, EricWF Reviewed By: mclow.lists Subscribers: christof, cfe-commits Differential Revision: https://reviews.llvm.org/D41347 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336164 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__errc | 218 +++++++++++++++++++++++++++++++++++++++ include/module.modulemap | 1 + include/system_error | 188 +-------------------------------- 3 files changed, 220 insertions(+), 187 deletions(-) create mode 100644 include/__errc diff --git a/include/__errc b/include/__errc new file mode 100644 index 000000000..d0f00b7f0 --- /dev/null +++ b/include/__errc @@ -0,0 +1,218 @@ +// -*- C++ -*- +//===---------------------------- __errc ----------------------------------===// +// +// 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___ERRC +#define _LIBCPP___ERRC + +/* + system_error synopsis + +namespace std +{ + +enum class errc +{ + address_family_not_supported, // EAFNOSUPPORT + address_in_use, // EADDRINUSE + address_not_available, // EADDRNOTAVAIL + already_connected, // EISCONN + argument_list_too_long, // E2BIG + argument_out_of_domain, // EDOM + bad_address, // EFAULT + bad_file_descriptor, // EBADF + bad_message, // EBADMSG + broken_pipe, // EPIPE + connection_aborted, // ECONNABORTED + connection_already_in_progress, // EALREADY + connection_refused, // ECONNREFUSED + connection_reset, // ECONNRESET + cross_device_link, // EXDEV + destination_address_required, // EDESTADDRREQ + device_or_resource_busy, // EBUSY + directory_not_empty, // ENOTEMPTY + executable_format_error, // ENOEXEC + file_exists, // EEXIST + file_too_large, // EFBIG + filename_too_long, // ENAMETOOLONG + function_not_supported, // ENOSYS + host_unreachable, // EHOSTUNREACH + identifier_removed, // EIDRM + illegal_byte_sequence, // EILSEQ + inappropriate_io_control_operation, // ENOTTY + interrupted, // EINTR + invalid_argument, // EINVAL + invalid_seek, // ESPIPE + io_error, // EIO + is_a_directory, // EISDIR + message_size, // EMSGSIZE + network_down, // ENETDOWN + network_reset, // ENETRESET + network_unreachable, // ENETUNREACH + no_buffer_space, // ENOBUFS + no_child_process, // ECHILD + no_link, // ENOLINK + no_lock_available, // ENOLCK + no_message_available, // ENODATA + no_message, // ENOMSG + no_protocol_option, // ENOPROTOOPT + no_space_on_device, // ENOSPC + no_stream_resources, // ENOSR + no_such_device_or_address, // ENXIO + no_such_device, // ENODEV + no_such_file_or_directory, // ENOENT + no_such_process, // ESRCH + not_a_directory, // ENOTDIR + not_a_socket, // ENOTSOCK + not_a_stream, // ENOSTR + not_connected, // ENOTCONN + not_enough_memory, // ENOMEM + not_supported, // ENOTSUP + operation_canceled, // ECANCELED + operation_in_progress, // EINPROGRESS + operation_not_permitted, // EPERM + operation_not_supported, // EOPNOTSUPP + operation_would_block, // EWOULDBLOCK + owner_dead, // EOWNERDEAD + permission_denied, // EACCES + protocol_error, // EPROTO + protocol_not_supported, // EPROTONOSUPPORT + read_only_file_system, // EROFS + resource_deadlock_would_occur, // EDEADLK + resource_unavailable_try_again, // EAGAIN + result_out_of_range, // ERANGE + state_not_recoverable, // ENOTRECOVERABLE + stream_timeout, // ETIME + text_file_busy, // ETXTBSY + timed_out, // ETIMEDOUT + too_many_files_open_in_system, // ENFILE + too_many_files_open, // EMFILE + too_many_links, // EMLINK + too_many_symbolic_link_levels, // ELOOP + value_too_large, // EOVERFLOW + wrong_protocol_type // EPROTOTYPE +}; + +*/ + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// Some error codes are not present on all platforms, so we provide equivalents +// for them: + +//enum class errc +_LIBCPP_DECLARE_STRONG_ENUM(errc) +{ + address_family_not_supported = EAFNOSUPPORT, + address_in_use = EADDRINUSE, + address_not_available = EADDRNOTAVAIL, + already_connected = EISCONN, + argument_list_too_long = E2BIG, + argument_out_of_domain = EDOM, + bad_address = EFAULT, + bad_file_descriptor = EBADF, + bad_message = EBADMSG, + broken_pipe = EPIPE, + connection_aborted = ECONNABORTED, + connection_already_in_progress = EALREADY, + connection_refused = ECONNREFUSED, + connection_reset = ECONNRESET, + cross_device_link = EXDEV, + destination_address_required = EDESTADDRREQ, + device_or_resource_busy = EBUSY, + directory_not_empty = ENOTEMPTY, + executable_format_error = ENOEXEC, + file_exists = EEXIST, + file_too_large = EFBIG, + filename_too_long = ENAMETOOLONG, + function_not_supported = ENOSYS, + host_unreachable = EHOSTUNREACH, + identifier_removed = EIDRM, + illegal_byte_sequence = EILSEQ, + inappropriate_io_control_operation = ENOTTY, + interrupted = EINTR, + invalid_argument = EINVAL, + invalid_seek = ESPIPE, + io_error = EIO, + is_a_directory = EISDIR, + message_size = EMSGSIZE, + network_down = ENETDOWN, + network_reset = ENETRESET, + network_unreachable = ENETUNREACH, + no_buffer_space = ENOBUFS, + no_child_process = ECHILD, + no_link = ENOLINK, + no_lock_available = ENOLCK, +#ifdef ENODATA + no_message_available = ENODATA, +#else + no_message_available = ENOMSG, +#endif + no_message = ENOMSG, + no_protocol_option = ENOPROTOOPT, + no_space_on_device = ENOSPC, +#ifdef ENOSR + no_stream_resources = ENOSR, +#else + no_stream_resources = ENOMEM, +#endif + no_such_device_or_address = ENXIO, + no_such_device = ENODEV, + no_such_file_or_directory = ENOENT, + no_such_process = ESRCH, + not_a_directory = ENOTDIR, + not_a_socket = ENOTSOCK, +#ifdef ENOSTR + not_a_stream = ENOSTR, +#else + not_a_stream = EINVAL, +#endif + not_connected = ENOTCONN, + not_enough_memory = ENOMEM, + not_supported = ENOTSUP, + operation_canceled = ECANCELED, + operation_in_progress = EINPROGRESS, + operation_not_permitted = EPERM, + operation_not_supported = EOPNOTSUPP, + operation_would_block = EWOULDBLOCK, + owner_dead = EOWNERDEAD, + permission_denied = EACCES, + protocol_error = EPROTO, + protocol_not_supported = EPROTONOSUPPORT, + read_only_file_system = EROFS, + resource_deadlock_would_occur = EDEADLK, + resource_unavailable_try_again = EAGAIN, + result_out_of_range = ERANGE, + state_not_recoverable = ENOTRECOVERABLE, +#ifdef ETIME + stream_timeout = ETIME, +#else + stream_timeout = ETIMEDOUT, +#endif + text_file_busy = ETXTBSY, + timed_out = ETIMEDOUT, + too_many_files_open_in_system = ENFILE, + too_many_files_open = EMFILE, + too_many_links = EMLINK, + too_many_symbolic_link_levels = ELOOP, + value_too_large = EOVERFLOW, + wrong_protocol_type = EPROTOTYPE +}; +_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(errc) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___ERRC diff --git a/include/module.modulemap b/include/module.modulemap index 5b3ebf48a..70f82a775 100644 --- a/include/module.modulemap +++ b/include/module.modulemap @@ -482,6 +482,7 @@ module std [system] { // FIXME: These should be private. module __bit_reference { header "__bit_reference" export * } module __debug { header "__debug" export * } + module __errc { header "__errc" export * } module __functional_base { header "__functional_base" export * } module __hash_table { header "__hash_table" export * } module __locale { header "__locale" export * } diff --git a/include/system_error b/include/system_error index c577edcee..f5d8d1145 100644 --- a/include/system_error +++ b/include/system_error @@ -120,88 +120,6 @@ public: const char* what() const noexcept; }; -enum class errc -{ - address_family_not_supported, // EAFNOSUPPORT - address_in_use, // EADDRINUSE - address_not_available, // EADDRNOTAVAIL - already_connected, // EISCONN - argument_list_too_long, // E2BIG - argument_out_of_domain, // EDOM - bad_address, // EFAULT - bad_file_descriptor, // EBADF - bad_message, // EBADMSG - broken_pipe, // EPIPE - connection_aborted, // ECONNABORTED - connection_already_in_progress, // EALREADY - connection_refused, // ECONNREFUSED - connection_reset, // ECONNRESET - cross_device_link, // EXDEV - destination_address_required, // EDESTADDRREQ - device_or_resource_busy, // EBUSY - directory_not_empty, // ENOTEMPTY - executable_format_error, // ENOEXEC - file_exists, // EEXIST - file_too_large, // EFBIG - filename_too_long, // ENAMETOOLONG - function_not_supported, // ENOSYS - host_unreachable, // EHOSTUNREACH - identifier_removed, // EIDRM - illegal_byte_sequence, // EILSEQ - inappropriate_io_control_operation, // ENOTTY - interrupted, // EINTR - invalid_argument, // EINVAL - invalid_seek, // ESPIPE - io_error, // EIO - is_a_directory, // EISDIR - message_size, // EMSGSIZE - network_down, // ENETDOWN - network_reset, // ENETRESET - network_unreachable, // ENETUNREACH - no_buffer_space, // ENOBUFS - no_child_process, // ECHILD - no_link, // ENOLINK - no_lock_available, // ENOLCK - no_message_available, // ENODATA - no_message, // ENOMSG - no_protocol_option, // ENOPROTOOPT - no_space_on_device, // ENOSPC - no_stream_resources, // ENOSR - no_such_device_or_address, // ENXIO - no_such_device, // ENODEV - no_such_file_or_directory, // ENOENT - no_such_process, // ESRCH - not_a_directory, // ENOTDIR - not_a_socket, // ENOTSOCK - not_a_stream, // ENOSTR - not_connected, // ENOTCONN - not_enough_memory, // ENOMEM - not_supported, // ENOTSUP - operation_canceled, // ECANCELED - operation_in_progress, // EINPROGRESS - operation_not_permitted, // EPERM - operation_not_supported, // EOPNOTSUPP - operation_would_block, // EWOULDBLOCK - owner_dead, // EOWNERDEAD - permission_denied, // EACCES - protocol_error, // EPROTO - protocol_not_supported, // EPROTONOSUPPORT - read_only_file_system, // EROFS - resource_deadlock_would_occur, // EDEADLK - resource_unavailable_try_again, // EAGAIN - result_out_of_range, // ERANGE - state_not_recoverable, // ENOTRECOVERABLE - stream_timeout, // ETIME - text_file_busy, // ETXTBSY - timed_out, // ETIMEDOUT - too_many_files_open_in_system, // ENFILE - too_many_files_open, // EMFILE - too_many_links, // EMLINK - too_many_symbolic_link_levels, // ELOOP - value_too_large, // EOVERFLOW - wrong_protocol_type // EPROTOTYPE -}; - template <> struct is_error_condition_enum : true_type { } @@ -225,8 +143,7 @@ template <> struct hash; */ -#include <__config> -#include +#include <__errc> #include #include #include <__functional_base> @@ -260,109 +177,6 @@ template _LIBCPP_INLINE_VAR constexpr size_t is_error_condition_enum_v = is_error_condition_enum<_Tp>::value; #endif -// Some error codes are not present on all platforms, so we provide equivalents -// for them: - -//enum class errc -_LIBCPP_DECLARE_STRONG_ENUM(errc) -{ - address_family_not_supported = EAFNOSUPPORT, - address_in_use = EADDRINUSE, - address_not_available = EADDRNOTAVAIL, - already_connected = EISCONN, - argument_list_too_long = E2BIG, - argument_out_of_domain = EDOM, - bad_address = EFAULT, - bad_file_descriptor = EBADF, - bad_message = EBADMSG, - broken_pipe = EPIPE, - connection_aborted = ECONNABORTED, - connection_already_in_progress = EALREADY, - connection_refused = ECONNREFUSED, - connection_reset = ECONNRESET, - cross_device_link = EXDEV, - destination_address_required = EDESTADDRREQ, - device_or_resource_busy = EBUSY, - directory_not_empty = ENOTEMPTY, - executable_format_error = ENOEXEC, - file_exists = EEXIST, - file_too_large = EFBIG, - filename_too_long = ENAMETOOLONG, - function_not_supported = ENOSYS, - host_unreachable = EHOSTUNREACH, - identifier_removed = EIDRM, - illegal_byte_sequence = EILSEQ, - inappropriate_io_control_operation = ENOTTY, - interrupted = EINTR, - invalid_argument = EINVAL, - invalid_seek = ESPIPE, - io_error = EIO, - is_a_directory = EISDIR, - message_size = EMSGSIZE, - network_down = ENETDOWN, - network_reset = ENETRESET, - network_unreachable = ENETUNREACH, - no_buffer_space = ENOBUFS, - no_child_process = ECHILD, - no_link = ENOLINK, - no_lock_available = ENOLCK, -#ifdef ENODATA - no_message_available = ENODATA, -#else - no_message_available = ENOMSG, -#endif - no_message = ENOMSG, - no_protocol_option = ENOPROTOOPT, - no_space_on_device = ENOSPC, -#ifdef ENOSR - no_stream_resources = ENOSR, -#else - no_stream_resources = ENOMEM, -#endif - no_such_device_or_address = ENXIO, - no_such_device = ENODEV, - no_such_file_or_directory = ENOENT, - no_such_process = ESRCH, - not_a_directory = ENOTDIR, - not_a_socket = ENOTSOCK, -#ifdef ENOSTR - not_a_stream = ENOSTR, -#else - not_a_stream = EINVAL, -#endif - not_connected = ENOTCONN, - not_enough_memory = ENOMEM, - not_supported = ENOTSUP, - operation_canceled = ECANCELED, - operation_in_progress = EINPROGRESS, - operation_not_permitted = EPERM, - operation_not_supported = EOPNOTSUPP, - operation_would_block = EWOULDBLOCK, - owner_dead = EOWNERDEAD, - permission_denied = EACCES, - protocol_error = EPROTO, - protocol_not_supported = EPROTONOSUPPORT, - read_only_file_system = EROFS, - resource_deadlock_would_occur = EDEADLK, - resource_unavailable_try_again = EAGAIN, - result_out_of_range = ERANGE, - state_not_recoverable = ENOTRECOVERABLE, -#ifdef ETIME - stream_timeout = ETIME, -#else - stream_timeout = ETIMEDOUT, -#endif - text_file_busy = ETXTBSY, - timed_out = ETIMEDOUT, - too_many_files_open_in_system = ENFILE, - too_many_files_open = EMFILE, - too_many_links = EMLINK, - too_many_symbolic_link_levels = ELOOP, - value_too_large = EOVERFLOW, - wrong_protocol_type = EPROTOTYPE -}; -_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(errc) - template <> struct _LIBCPP_TEMPLATE_VIS is_error_condition_enum : true_type { }; -- GitLab From 8fdc491860efbccb65ab2f01ec25e13b024da538 Mon Sep 17 00:00:00 2001 From: Zhihao Yuan Date: Tue, 3 Jul 2018 04:01:44 +0000 Subject: [PATCH 009/495] [libc++] Install the missing header __errc Summary: Omitted from D41347. Reviewers: EricWF Subscribers: mgorny, christof, ldionne, cfe-commits Differential Revision: https://reviews.llvm.org/D48864 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336165 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 6bd75915d..be0e10d50 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -2,6 +2,7 @@ set(files __bit_reference __bsd_locale_defaults.h __bsd_locale_fallbacks.h + __errc __debug __functional_03 __functional_base -- GitLab From e5a3de1bd11f0e506356ced481e6f933661da1af Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 4 Jul 2018 20:16:05 +0000 Subject: [PATCH 010/495] Remove old workaround that is no longer needed git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336297 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/libcxx/test/config.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/utils/libcxx/test/config.py b/utils/libcxx/test/config.py index 73357b8ab..34753be84 100644 --- a/utils/libcxx/test/config.py +++ b/utils/libcxx/test/config.py @@ -933,9 +933,6 @@ class Configuration(object): # FIXME: Enable the two warnings below. self.cxx.addWarningFlagIfSupported('-Wno-conversion') self.cxx.addWarningFlagIfSupported('-Wno-unused-local-typedef') - # FIXME: Remove this warning once the min/max handling patch lands - # See https://reviews.llvm.org/D33080 - self.cxx.addWarningFlagIfSupported('-Wno-#warnings') std = self.get_lit_conf('std', None) if std in ['c++98', 'c++03']: # The '#define static_assert' provided by libc++ in C++03 mode -- GitLab From 50e0c14078aced352faa8ece45ac7ee3bff2253d Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Thu, 5 Jul 2018 16:16:03 +0000 Subject: [PATCH 011/495] [NFC] Add to the synopsis of Summary: It is part of the synopsis in the Standard and does include it, but it was left out of the synopsis comment. Reviewers: EricWF, mclow.lists Subscribers: christof, llvm-commits Differential Revision: https://reviews.llvm.org/D48611 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336368 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/utility | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/utility b/include/utility index f11d58019..8fdaf65db 100644 --- a/include/utility +++ b/include/utility @@ -14,6 +14,8 @@ /* utility synopsis +#include + namespace std { -- GitLab From 79aa4f32d0efe6cc97b92d7647db4dea154ad82d Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Thu, 5 Jul 2018 16:49:38 +0000 Subject: [PATCH 012/495] [libc++] Replace uses of _LIBCPP_ALWAYS_INLINE by _LIBCPP_INLINE_VISIBILITY Summary: We never actually mean to always inline a function -- all the uses of the macro I could find are actually attempts to control the visibility of symbols. This is better described by _LIBCPP_INLINE_VISIBILITY, which is actually always defined the same. This change is orthogonal to the decision of what we're actually going to do with _LIBCPP_INLINE_VISIBILITY -- it just simplifies things by having one canonical way of doing things. Reviewers: EricWF Subscribers: christof, llvm-commits, dexonsmith, erikvanderpoel, mclow.lists Differential Revision: https://reviews.llvm.org/D48892 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336369 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/DesignDocs/VisibilityMacros.rst | 8 +- include/__bsd_locale_fallbacks.h | 22 +-- include/__config | 16 +- include/__locale | 168 ++++++++--------- include/__nullptr | 16 +- include/any | 6 +- include/cmath | 12 +- include/codecvt | 36 ++-- include/exception | 4 +- include/experimental/dynarray | 2 +- include/experimental/filesystem | 12 +- include/functional | 2 +- include/future | 2 +- include/initializer_list | 10 +- include/ios | 34 ++-- include/locale | 176 +++++++++--------- include/math.h | 24 +-- include/memory | 6 +- include/new | 2 +- include/ostream | 4 +- include/regex | 2 +- include/stdexcept | 16 +- include/streambuf | 14 +- include/support/android/locale_bionic.h | 12 +- include/support/xlocale/__posix_l_fallback.h | 78 ++++---- include/support/xlocale/__strtonum_fallback.h | 24 +-- include/system_error | 48 ++--- include/typeinfo | 2 +- include/vector | 2 +- src/support/win32/thread_win32.cpp | 4 +- 30 files changed, 377 insertions(+), 387 deletions(-) diff --git a/docs/DesignDocs/VisibilityMacros.rst b/docs/DesignDocs/VisibilityMacros.rst index 993ce2cca..69a09974a 100644 --- a/docs/DesignDocs/VisibilityMacros.rst +++ b/docs/DesignDocs/VisibilityMacros.rst @@ -41,10 +41,10 @@ Visibility Macros library and has an empty definition otherwise. **_LIBCPP_INLINE_VISIBILITY** - Mark a function as hidden and force inlining whenever possible. - -**_LIBCPP_ALWAYS_INLINE** - A synonym for `_LIBCPP_INLINE_VISIBILITY` + Mark a function as not being part of the ABI of any final linked image that + uses it, and also as being internal to each TU that uses that function. In + other words, the address of a function marked with this attribute is not + guaranteed to be the same across translation units. **_LIBCPP_TYPE_VIS** Mark a type's typeinfo, vtable and members as having default visibility. diff --git a/include/__bsd_locale_fallbacks.h b/include/__bsd_locale_fallbacks.h index 5e9e09483..3097b0141 100644 --- a/include/__bsd_locale_fallbacks.h +++ b/include/__bsd_locale_fallbacks.h @@ -24,28 +24,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l) { __libcpp_locale_guard __current(__l); return MB_CUR_MAX; } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY wint_t __libcpp_btowc_l(int __c, locale_t __l) { __libcpp_locale_guard __current(__l); return btowc(__c); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY int __libcpp_wctob_l(wint_t __c, locale_t __l) { __libcpp_locale_guard __current(__l); return wctob(__c); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc, size_t __len, mbstate_t *__ps, locale_t __l) { @@ -53,14 +53,14 @@ size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc, return wcsnrtombs(__dest, __src, __nwc, __len, __ps); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l) { __libcpp_locale_guard __current(__l); return wcrtomb(__s, __wc, __ps); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms, size_t __len, mbstate_t *__ps, locale_t __l) { @@ -68,7 +68,7 @@ size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms, return mbsnrtowcs(__dest, __src, __nms, __len, __ps); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) { @@ -76,28 +76,28 @@ size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n, return mbrtowc(__pwc, __s, __n, __ps); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY int __libcpp_mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l) { __libcpp_locale_guard __current(__l); return mbtowc(__pwc, __pmb, __max); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) { __libcpp_locale_guard __current(__l); return mbrlen(__s, __n, __ps); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY lconv *__libcpp_localeconv_l(locale_t __l) { __libcpp_locale_guard __current(__l); return localeconv(); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len, mbstate_t *__ps, locale_t __l) { diff --git a/include/__config b/include/__config index 52c7142ff..233c2b3ab 100644 --- a/include/__config +++ b/include/__config @@ -672,11 +672,9 @@ namespace std { #if defined(_LIBCPP_COMPILER_MSVC) # define _LIBCPP_INLINE_VISIBILITY __forceinline -# define _LIBCPP_ALWAYS_INLINE __forceinline # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __forceinline #else # define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__always_inline__)) -# define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__ ((__always_inline__)) #endif @@ -771,14 +769,6 @@ namespace std { # endif #endif -#ifndef _LIBCPP_ALWAYS_INLINE -# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) -# define _LIBCPP_ALWAYS_INLINE __attribute__ ((__visibility__("hidden"), __always_inline__)) -# else -# define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) -# endif -#endif - #ifndef _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__((__visibility__("default"), __always_inline__)) @@ -889,9 +879,9 @@ template struct __static_assert_check {}; # define _LIBCPP_DECLARE_STRONG_ENUM(x) struct _LIBCPP_TYPE_VIS x { enum __lx # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \ __lx __v_; \ - _LIBCPP_ALWAYS_INLINE x(__lx __v) : __v_(__v) {} \ - _LIBCPP_ALWAYS_INLINE explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ - _LIBCPP_ALWAYS_INLINE operator int() const {return __v_;} \ + _LIBCPP_INLINE_VISIBILITY x(__lx __v) : __v_(__v) {} \ + _LIBCPP_INLINE_VISIBILITY explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ + _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;} \ }; #else // _LIBCPP_HAS_NO_STRONG_ENUMS # define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_ENUM_VIS x diff --git a/include/__locale b/include/__locale index c293b81fb..f43e7b430 100644 --- a/include/__locale +++ b/include/__locale @@ -469,7 +469,7 @@ public: static const mask alnum = alpha | digit; static const mask graph = alnum | punct; - _LIBCPP_ALWAYS_INLINE ctype_base() {} + _LIBCPP_INLINE_VISIBILITY ctype_base() {} }; template class _LIBCPP_TEMPLATE_VIS ctype; @@ -482,77 +482,77 @@ class _LIBCPP_TYPE_VIS ctype public: typedef wchar_t char_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit ctype(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool is(mask __m, char_type __c) const { return do_is(__m, __c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const { return do_is(__low, __high, __vec); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* scan_is(mask __m, const char_type* __low, const char_type* __high) const { return do_scan_is(__m, __low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const { return do_scan_not(__m, __low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type toupper(char_type __c) const { return do_toupper(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* toupper(char_type* __low, const char_type* __high) const { return do_toupper(__low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type tolower(char_type __c) const { return do_tolower(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* tolower(char_type* __low, const char_type* __high) const { return do_tolower(__low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type widen(char __c) const { return do_widen(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char* widen(const char* __low, const char* __high, char_type* __to) const { return do_widen(__low, __high, __to); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char narrow(char_type __c, char __dfault) const { return do_narrow(__c, __dfault); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const { return do_narrow(__low, __high, __dfault, __to); @@ -587,13 +587,13 @@ public: explicit ctype(const mask* __tab = 0, bool __del = false, size_t __refs = 0); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool is(mask __m, char_type __c) const { return isascii(__c) ? (__tab_[static_cast(__c)] & __m) !=0 : false; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const { for (; __low != __high; ++__low, ++__vec) @@ -601,7 +601,7 @@ public: return __low; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* scan_is (mask __m, const char_type* __low, const char_type* __high) const { for (; __low != __high; ++__low) @@ -610,7 +610,7 @@ public: return __low; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const { for (; __low != __high; ++__low) @@ -619,49 +619,49 @@ public: return __low; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type toupper(char_type __c) const { return do_toupper(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* toupper(char_type* __low, const char_type* __high) const { return do_toupper(__low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type tolower(char_type __c) const { return do_tolower(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* tolower(char_type* __low, const char_type* __high) const { return do_tolower(__low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type widen(char __c) const { return do_widen(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char* widen(const char* __low, const char* __high, char_type* __to) const { return do_widen(__low, __high, __to); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char narrow(char_type __c, char __dfault) const { return do_narrow(__c, __dfault); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const { return do_narrow(__low, __high, __dfault, __to); @@ -674,7 +674,7 @@ public: #else static const size_t table_size = 256; // FIXME: Don't hardcode this. #endif - _LIBCPP_ALWAYS_INLINE const mask* table() const _NOEXCEPT {return __tab_;} + _LIBCPP_INLINE_VISIBILITY const mask* table() const _NOEXCEPT {return __tab_;} static const mask* classic_table() _NOEXCEPT; #if defined(__GLIBC__) || defined(__EMSCRIPTEN__) static const int* __classic_upper_table() _NOEXCEPT; @@ -854,7 +854,7 @@ tolower(_CharT __c, const locale& __loc) class _LIBCPP_TYPE_VIS codecvt_base { public: - _LIBCPP_ALWAYS_INLINE codecvt_base() {} + _LIBCPP_INLINE_VISIBILITY codecvt_base() {} enum result {ok, partial, error, noconv}; }; @@ -874,11 +874,11 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -886,14 +886,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -901,25 +901,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int max_length() const _NOEXCEPT { return do_max_length(); @@ -928,7 +928,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {} @@ -963,7 +963,7 @@ public: explicit codecvt(size_t __refs = 0); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -971,14 +971,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -986,25 +986,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int max_length() const _NOEXCEPT { return do_max_length(); @@ -1043,11 +1043,11 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -1055,14 +1055,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -1070,25 +1070,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int max_length() const _NOEXCEPT { return do_max_length(); @@ -1097,7 +1097,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {} @@ -1129,11 +1129,11 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -1141,14 +1141,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -1156,25 +1156,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int max_length() const _NOEXCEPT { return do_max_length(); @@ -1183,7 +1183,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {} @@ -1210,10 +1210,10 @@ class _LIBCPP_TEMPLATE_VIS codecvt_byname : public codecvt<_InternT, _ExternT, _StateT> { public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt_byname(const char* __nm, size_t __refs = 0) : codecvt<_InternT, _ExternT, _StateT>(__nm, __refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt_byname(const string& __nm, size_t __refs = 0) : codecvt<_InternT, _ExternT, _StateT>(__nm.c_str(), __refs) {} protected: @@ -1244,7 +1244,7 @@ template <> struct __narrow_to_utf8<8> { template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const { @@ -1258,13 +1258,13 @@ template <> struct __narrow_to_utf8<16> : public codecvt { - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY __narrow_to_utf8() : codecvt(1) {} ~__narrow_to_utf8(); template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const { @@ -1292,13 +1292,13 @@ template <> struct __narrow_to_utf8<32> : public codecvt { - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY __narrow_to_utf8() : codecvt(1) {} ~__narrow_to_utf8(); template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const { @@ -1334,7 +1334,7 @@ template <> struct __widen_from_utf8<8> { template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const { @@ -1348,13 +1348,13 @@ template <> struct __widen_from_utf8<16> : public codecvt { - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY __widen_from_utf8() : codecvt(1) {} ~__widen_from_utf8(); template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const { @@ -1382,13 +1382,13 @@ template <> struct __widen_from_utf8<32> : public codecvt { - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY __widen_from_utf8() : codecvt(1) {} ~__widen_from_utf8(); template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const { @@ -1426,11 +1426,11 @@ public: explicit numpunct(size_t __refs = 0); - _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} - _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} - _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} - _LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();} - _LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();} + _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();} + _LIBCPP_INLINE_VISIBILITY string_type truename() const {return do_truename();} + _LIBCPP_INLINE_VISIBILITY string_type falsename() const {return do_falsename();} static locale::id id; @@ -1457,11 +1457,11 @@ public: explicit numpunct(size_t __refs = 0); - _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} - _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} - _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} - _LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();} - _LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();} + _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();} + _LIBCPP_INLINE_VISIBILITY string_type truename() const {return do_truename();} + _LIBCPP_INLINE_VISIBILITY string_type falsename() const {return do_falsename();} static locale::id id; diff --git a/include/__nullptr b/include/__nullptr index a341234f5..aa3b4d214 100644 --- a/include/__nullptr +++ b/include/__nullptr @@ -27,24 +27,24 @@ struct _LIBCPP_TEMPLATE_VIS nullptr_t struct __nat {int __for_bool_;}; - _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {} - _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {} - _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;} template - _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator _Tp* () const {return 0;} template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY operator _Tp _Up::* () const {return 0;} - friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;} - friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;} + friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;} + friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;} }; -inline _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);} +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);} #define nullptr _VSTD::__get_nullptr_t() diff --git a/include/any b/include/any index d7161b0d6..9bd2f53c5 100644 --- a/include/any +++ b/include/any @@ -104,7 +104,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_any_cast() { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -304,7 +304,7 @@ private: __any_imp::_Buffer __buf; }; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void * __call(_Action __a, any * __other = nullptr, type_info const * __info = nullptr, const void* __fallback_info = nullptr) const @@ -312,7 +312,7 @@ private: return __h(__a, this, __other, __info, __fallback_info); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void * __call(_Action __a, any * __other = nullptr, type_info const * __info = nullptr, const void* __fallback_info = nullptr) diff --git a/include/cmath b/include/cmath index 917928a1f..ffb1c46c7 100644 --- a/include/cmath +++ b/include/cmath @@ -547,7 +547,7 @@ hypot(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT #endif template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -559,7 +559,7 @@ __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -567,7 +567,7 @@ __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -579,7 +579,7 @@ __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -587,7 +587,7 @@ __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -599,7 +599,7 @@ __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT { diff --git a/include/codecvt b/include/codecvt index 46f56acff..5eb9d1549 100644 --- a/include/codecvt +++ b/include/codecvt @@ -86,7 +86,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -121,7 +121,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -156,7 +156,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -186,11 +186,11 @@ class _LIBCPP_TEMPLATE_VIS codecvt_utf8 : public __codecvt_utf8<_Elem> { public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt_utf8(size_t __refs = 0) : __codecvt_utf8<_Elem>(__refs, _Maxcode, _Mode) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~codecvt_utf8() {} }; @@ -209,7 +209,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -244,7 +244,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -279,7 +279,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -314,7 +314,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -349,7 +349,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -384,7 +384,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -414,11 +414,11 @@ class _LIBCPP_TEMPLATE_VIS codecvt_utf16 : public __codecvt_utf16<_Elem, _Mode & little_endian> { public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt_utf16(size_t __refs = 0) : __codecvt_utf16<_Elem, _Mode & little_endian>(__refs, _Maxcode, _Mode) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~codecvt_utf16() {} }; @@ -437,7 +437,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -472,7 +472,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -507,7 +507,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -537,11 +537,11 @@ class _LIBCPP_TEMPLATE_VIS codecvt_utf8_utf16 : public __codecvt_utf8_utf16<_Elem> { public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt_utf8_utf16(size_t __refs = 0) : __codecvt_utf8_utf16<_Elem>(__refs, _Maxcode, _Mode) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~codecvt_utf8_utf16() {} }; diff --git a/include/exception b/include/exception index 79bd6ac2a..b517486b5 100644 --- a/include/exception +++ b/include/exception @@ -259,7 +259,7 @@ struct __throw_with_nested; template struct __throw_with_nested<_Tp, _Up, true> { - _LIBCPP_NORETURN static inline _LIBCPP_ALWAYS_INLINE void + _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void #ifndef _LIBCPP_CXX03_LANG __do_throw(_Tp&& __t) #else @@ -272,7 +272,7 @@ struct __throw_with_nested<_Tp, _Up, true> { template struct __throw_with_nested<_Tp, _Up, false> { - _LIBCPP_NORETURN static inline _LIBCPP_ALWAYS_INLINE void + _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void #ifndef _LIBCPP_CXX03_LANG __do_throw(_Tp&& __t) #else diff --git a/include/experimental/dynarray b/include/experimental/dynarray index cebfc208d..a60c87c3f 100644 --- a/include/experimental/dynarray +++ b/include/experimental/dynarray @@ -133,7 +133,7 @@ public: private: size_t __size_; value_type * __base_; - _LIBCPP_ALWAYS_INLINE dynarray () noexcept : __size_(0), __base_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY dynarray () noexcept : __size_(0), __base_(nullptr) {} static inline _LIBCPP_INLINE_VISIBILITY value_type* __allocate(size_t __count) { diff --git a/include/experimental/filesystem b/include/experimental/filesystem index f29e23e18..1ca179699 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -470,23 +470,23 @@ public: file_status& operator=(file_status&&) _NOEXCEPT = default; // observers - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY file_type type() const _NOEXCEPT { return __ft_; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY perms permissions() const _NOEXCEPT { return __prms_; } // modifiers - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void type(file_type __ft) _NOEXCEPT { __ft_ = __ft; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void permissions(perms __p) _NOEXCEPT { __prms_ = __p; } @@ -1106,7 +1106,7 @@ private: string_type __pn_; }; -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) _NOEXCEPT { __lhs.swap(__rhs); } @@ -1298,7 +1298,7 @@ private: }; template -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_NO_EXCEPTIONS void __throw_filesystem_error(_Args && ...__args) { diff --git a/include/functional b/include/functional index bb0bdf151..80261895e 100644 --- a/include/functional +++ b/include/functional @@ -1399,7 +1399,7 @@ public: #endif }; -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_function_call() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/future b/include/future index 536574e75..528091b04 100644 --- a/include/future +++ b/include/future @@ -514,7 +514,7 @@ public: virtual ~future_error() _NOEXCEPT; }; -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_NO_EXCEPTIONS _LIBCPP_AVAILABILITY_FUTURE_ERROR #endif diff --git a/include/initializer_list b/include/initializer_list index 8c234aaaa..b934637b8 100644 --- a/include/initializer_list +++ b/include/initializer_list @@ -61,7 +61,7 @@ class _LIBCPP_TEMPLATE_VIS initializer_list const _Ep* __begin_; size_t __size_; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 initializer_list(const _Ep* __b, size_t __s) _NOEXCEPT : __begin_(__b), @@ -76,19 +76,19 @@ public: typedef const _Ep* iterator; typedef const _Ep* const_iterator; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 initializer_list() _NOEXCEPT : __begin_(nullptr), __size_(0) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 size_t size() const _NOEXCEPT {return __size_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const _Ep* begin() const _NOEXCEPT {return __begin_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const _Ep* end() const _NOEXCEPT {return __begin_ + __size_;} }; diff --git a/include/ios b/include/ios index 6e32d0fe6..040b2d4e0 100644 --- a/include/ios +++ b/include/ios @@ -337,9 +337,9 @@ protected: } void init(void* __sb); - _LIBCPP_ALWAYS_INLINE void* rdbuf() const {return __rdbuf_;} + _LIBCPP_INLINE_VISIBILITY void* rdbuf() const {return __rdbuf_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void rdbuf(void* __sb) { __rdbuf_ = __sb; @@ -351,7 +351,7 @@ protected: void move(ios_base&); void swap(ios_base&) _NOEXCEPT; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void set_rdbuf(void* __sb) { __rdbuf_ = __sb; @@ -599,26 +599,26 @@ public: // we give it internal linkage. #if defined(_LIBCPP_CXX03_LANG) - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY operator __cxx03_bool::__bool_type() const { return !fail() ? &__cxx03_bool::__true_value : nullptr; } #else - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const {return !fail();} #endif - _LIBCPP_ALWAYS_INLINE bool operator!() const {return fail();} - _LIBCPP_ALWAYS_INLINE iostate rdstate() const {return ios_base::rdstate();} - _LIBCPP_ALWAYS_INLINE void clear(iostate __state = goodbit) {ios_base::clear(__state);} - _LIBCPP_ALWAYS_INLINE void setstate(iostate __state) {ios_base::setstate(__state);} - _LIBCPP_ALWAYS_INLINE bool good() const {return ios_base::good();} - _LIBCPP_ALWAYS_INLINE bool eof() const {return ios_base::eof();} - _LIBCPP_ALWAYS_INLINE bool fail() const {return ios_base::fail();} - _LIBCPP_ALWAYS_INLINE bool bad() const {return ios_base::bad();} + _LIBCPP_INLINE_VISIBILITY bool operator!() const {return fail();} + _LIBCPP_INLINE_VISIBILITY iostate rdstate() const {return ios_base::rdstate();} + _LIBCPP_INLINE_VISIBILITY void clear(iostate __state = goodbit) {ios_base::clear(__state);} + _LIBCPP_INLINE_VISIBILITY void setstate(iostate __state) {ios_base::setstate(__state);} + _LIBCPP_INLINE_VISIBILITY bool good() const {return ios_base::good();} + _LIBCPP_INLINE_VISIBILITY bool eof() const {return ios_base::eof();} + _LIBCPP_INLINE_VISIBILITY bool fail() const {return ios_base::fail();} + _LIBCPP_INLINE_VISIBILITY bool bad() const {return ios_base::bad();} - _LIBCPP_ALWAYS_INLINE iostate exceptions() const {return ios_base::exceptions();} - _LIBCPP_ALWAYS_INLINE void exceptions(iostate __iostate) {ios_base::exceptions(__iostate);} + _LIBCPP_INLINE_VISIBILITY iostate exceptions() const {return ios_base::exceptions();} + _LIBCPP_INLINE_VISIBILITY void exceptions(iostate __iostate) {ios_base::exceptions(__iostate);} // 27.5.4.1 Constructor/destructor: _LIBCPP_INLINE_VISIBILITY @@ -652,7 +652,7 @@ public: char_type widen(char __c) const; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY basic_ios() {// purposefully does no initialization } _LIBCPP_INLINE_VISIBILITY @@ -661,7 +661,7 @@ protected: _LIBCPP_INLINE_VISIBILITY void move(basic_ios& __rhs); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void move(basic_ios&& __rhs) {move(__rhs);} #endif _LIBCPP_INLINE_VISIBILITY diff --git a/include/locale b/include/locale index 52885b768..e240799f3 100644 --- a/include/locale +++ b/include/locale @@ -573,81 +573,81 @@ public: typedef _CharT char_type; typedef _InputIterator iter_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit num_get(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { @@ -657,7 +657,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~num_get() {} template @@ -1261,60 +1261,60 @@ public: typedef _CharT char_type; typedef _OutputIterator iter_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit num_put(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { @@ -1324,7 +1324,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~num_put() {} virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, @@ -1738,7 +1738,7 @@ protected: virtual const string_type& __x() const; virtual const string_type& __X() const; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~__time_get_c_storage() {} }; @@ -1770,52 +1770,52 @@ public: typedef time_base::dateorder dateorder; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_get(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY dateorder date_order() const { return this->do_date_order(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_time(__b, __e, __iob, __err, __tm); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_date(__b, __e, __iob, __err, __tm); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_weekday(__b, __e, __iob, __err, __tm); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_monthname(__b, __e, __iob, __err, __tm); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_year(__b, __e, __iob, __err, __tm); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm *__tm, char __fmt, char __mod = 0) const @@ -1830,7 +1830,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~time_get() {} virtual dateorder do_date_order() const; @@ -2399,7 +2399,7 @@ protected: explicit __time_get_storage(const char* __nm); explicit __time_get_storage(const string& __nm); - _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {} + _LIBCPP_INLINE_VISIBILITY ~__time_get_storage() {} time_base::dateorder __do_date_order() const; @@ -2458,7 +2458,7 @@ class _LIBCPP_TYPE_VIS __time_put { locale_t __loc_; protected: - _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} + _LIBCPP_INLINE_VISIBILITY __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} __time_put(const char* __nm); __time_put(const string& __nm); ~__time_put(); @@ -2477,14 +2477,14 @@ public: typedef _CharT char_type; typedef _OutputIterator iter_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_put(size_t __refs = 0) : locale::facet(__refs) {} iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) const; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, char __fmt, char __mod = 0) const { @@ -2494,16 +2494,16 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~time_put() {} virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_put(const char* __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_put(const string& __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {} @@ -2572,16 +2572,16 @@ class _LIBCPP_TEMPLATE_VIS time_put_byname : public time_put<_CharT, _OutputIterator> { public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_put_byname(const char* __nm, size_t __refs = 0) : time_put<_CharT, _OutputIterator>(__nm, __refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_put_byname(const string& __nm, size_t __refs = 0) : time_put<_CharT, _OutputIterator>(__nm, __refs) {} protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~time_put_byname() {} }; @@ -2596,7 +2596,7 @@ public: enum part {none, space, symbol, sign, value}; struct pattern {char field[4];}; - _LIBCPP_ALWAYS_INLINE money_base() {} + _LIBCPP_INLINE_VISIBILITY money_base() {} }; // moneypunct @@ -2610,25 +2610,25 @@ public: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} - _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} - _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} - _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();} - _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();} - _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();} - _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();} - _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();} - _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();} + _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();} + _LIBCPP_INLINE_VISIBILITY string_type curr_symbol() const {return do_curr_symbol();} + _LIBCPP_INLINE_VISIBILITY string_type positive_sign() const {return do_positive_sign();} + _LIBCPP_INLINE_VISIBILITY string_type negative_sign() const {return do_negative_sign();} + _LIBCPP_INLINE_VISIBILITY int frac_digits() const {return do_frac_digits();} + _LIBCPP_INLINE_VISIBILITY pattern pos_format() const {return do_pos_format();} + _LIBCPP_INLINE_VISIBILITY pattern neg_format() const {return do_neg_format();} static locale::id id; static const bool intl = _International; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~moneypunct() {} virtual char_type do_decimal_point() const {return numeric_limits::max();} @@ -2668,16 +2668,16 @@ public: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit moneypunct_byname(const char* __nm, size_t __refs = 0) : moneypunct<_CharT, _International>(__refs) {init(__nm);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit moneypunct_byname(const string& __nm, size_t __refs = 0) : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());} protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~moneypunct_byname() {} virtual char_type do_decimal_point() const {return __decimal_point_;} @@ -2723,7 +2723,7 @@ protected: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE __money_get() {} + _LIBCPP_INLINE_VISIBILITY __money_get() {} static void __gather_info(bool __intl, const locale& __loc, money_base::pattern& __pat, char_type& __dp, @@ -2781,18 +2781,18 @@ public: typedef _InputIterator iter_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit money_get(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { return do_get(__b, __e, __intl, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { @@ -2803,7 +2803,7 @@ public: protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~money_get() {} virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl, @@ -3163,7 +3163,7 @@ protected: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE __money_put() {} + _LIBCPP_INLINE_VISIBILITY __money_put() {} static void __gather_info(bool __intl, bool __neg, const locale& __loc, money_base::pattern& __pat, char_type& __dp, @@ -3339,18 +3339,18 @@ public: typedef _OutputIterator iter_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit money_put(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { return do_put(__s, __intl, __iob, __fl, __units); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { @@ -3360,7 +3360,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~money_put() {} virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, @@ -3489,7 +3489,7 @@ class _LIBCPP_TYPE_VIS messages_base public: typedef ptrdiff_t catalog; - _LIBCPP_ALWAYS_INLINE messages_base() {} + _LIBCPP_INLINE_VISIBILITY messages_base() {} }; template @@ -3501,24 +3501,24 @@ public: typedef _CharT char_type; typedef basic_string<_CharT> string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit messages(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY catalog open(const basic_string& __nm, const locale& __loc) const { return do_open(__nm, __loc); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY string_type get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { return do_get(__c, __set, __msgid, __dflt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void close(catalog __c) const { do_close(__c); @@ -3527,7 +3527,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~messages() {} virtual catalog do_open(const basic_string&, const locale&) const; @@ -3600,16 +3600,16 @@ public: typedef messages_base::catalog catalog; typedef basic_string<_CharT> string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit messages_byname(const char*, size_t __refs = 0) : messages<_CharT>(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit messages_byname(const string&, size_t __refs = 0) : messages<_CharT>(__refs) {} protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~messages_byname() {} }; @@ -3637,43 +3637,43 @@ private: wstring_convert(const wstring_convert& __wc); wstring_convert& operator=(const wstring_convert& __wc); public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY wstring_convert(_Codecvt* __pcvt, state_type __state); _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err = wide_string()); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY wstring_convert(wstring_convert&& __wc); #endif ~wstring_convert(); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY wide_string from_bytes(char __byte) {return from_bytes(&__byte, &__byte+1);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY wide_string from_bytes(const char* __ptr) {return from_bytes(__ptr, __ptr + char_traits::length(__ptr));} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY wide_string from_bytes(const byte_string& __str) {return from_bytes(__str.data(), __str.data() + __str.size());} wide_string from_bytes(const char* __first, const char* __last); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY byte_string to_bytes(_Elem __wchar) {return to_bytes(&__wchar, &__wchar+1);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY byte_string to_bytes(const _Elem* __wptr) {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY byte_string to_bytes(const wide_string& __wstr) {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());} byte_string to_bytes(const _Elem* __first, const _Elem* __last); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY size_t converted() const _NOEXCEPT {return __cvtcount_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY state_type state() const {return __cvtstate_;} }; diff --git a/include/math.h b/include/math.h index 658ba93be..3cc72aa27 100644 --- a/include/math.h +++ b/include/math.h @@ -314,7 +314,7 @@ extern "C++" { #ifdef signbit template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_signbit(_A1 __lcpp_x) _NOEXCEPT { @@ -376,7 +376,7 @@ signbit(_A1) _NOEXCEPT #ifdef fpclassify template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY int __libcpp_fpclassify(_A1 __lcpp_x) _NOEXCEPT { @@ -422,7 +422,7 @@ fpclassify(_A1 __lcpp_x) _NOEXCEPT #ifdef isfinite template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT { @@ -456,7 +456,7 @@ isfinite(_A1) _NOEXCEPT #ifdef isinf template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT { @@ -504,7 +504,7 @@ isinf(long double __lcpp_x) _NOEXCEPT { return __libcpp_isinf(__lcpp_x); } #ifdef isnan template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT { @@ -548,7 +548,7 @@ isnan(long double __lcpp_x) _NOEXCEPT { return __libcpp_isnan(__lcpp_x); } #ifdef isnormal template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isnormal(_A1 __lcpp_x) _NOEXCEPT { @@ -578,7 +578,7 @@ isnormal(_A1 __lcpp_x) _NOEXCEPT #ifdef isgreater template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -608,7 +608,7 @@ isgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef isgreaterequal template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isgreaterequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -638,7 +638,7 @@ isgreaterequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef isless template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isless(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -668,7 +668,7 @@ isless(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef islessequal template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_islessequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -698,7 +698,7 @@ islessequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef islessgreater template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_islessgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -728,7 +728,7 @@ islessgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef isunordered template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isunordered(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { diff --git a/include/memory b/include/memory index 31d4e4fac..fd830d7ed 100644 --- a/include/memory +++ b/include/memory @@ -679,7 +679,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY _ValueType __libcpp_relaxed_load(_ValueType const* __value) { #if !defined(_LIBCPP_HAS_NO_THREADS) && \ defined(__ATOMIC_RELAXED) && \ @@ -691,7 +691,7 @@ _ValueType __libcpp_relaxed_load(_ValueType const* __value) { } template -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY _ValueType __libcpp_acquire_load(_ValueType const* __value) { #if !defined(_LIBCPP_HAS_NO_THREADS) && \ defined(__ATOMIC_ACQUIRE) && \ @@ -3483,7 +3483,7 @@ public: virtual const char* what() const _NOEXCEPT; }; -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_weak_ptr() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/new b/include/new index e42ffad27..b5dc05542 100644 --- a/include/new +++ b/include/new @@ -281,7 +281,7 @@ inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate(void* __ptr, size_t __ } #ifdef _LIBCPP_BAD_ARRAY_LENGTH_DEFINED -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_NO_EXCEPTIONS _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH #endif diff --git a/include/ostream b/include/ostream index 197636eac..5404e0dca 100644 --- a/include/ostream +++ b/include/ostream @@ -232,7 +232,7 @@ public: basic_ostream& seekp(off_type __off, ios_base::seekdir __dir); protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY basic_ostream() {} // extension, intentially does not initialize }; @@ -249,7 +249,7 @@ public: explicit sentry(basic_ostream<_CharT, _Traits>& __os); ~sentry(); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const {return __ok_;} }; diff --git a/include/regex b/include/regex index 612fa84ce..84aacc029 100644 --- a/include/regex +++ b/include/regex @@ -968,7 +968,7 @@ public: }; template -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_regex_error() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/stdexcept b/include/stdexcept index 95a96cc07..6533497e4 100644 --- a/include/stdexcept +++ b/include/stdexcept @@ -185,7 +185,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // in the dylib _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_runtime_error(const char*); -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_logic_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -196,7 +196,7 @@ void __throw_logic_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_domain_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -207,7 +207,7 @@ void __throw_domain_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_invalid_argument(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -218,7 +218,7 @@ void __throw_invalid_argument(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_length_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -229,7 +229,7 @@ void __throw_length_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_out_of_range(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -240,7 +240,7 @@ void __throw_out_of_range(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_range_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -251,7 +251,7 @@ void __throw_range_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_overflow_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -262,7 +262,7 @@ void __throw_overflow_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_underflow_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/streambuf b/include/streambuf index e409d2106..7887a0502 100644 --- a/include/streambuf +++ b/include/streambuf @@ -236,9 +236,9 @@ protected: void swap(basic_streambuf& __rhs); // 27.6.2.3.2 Get area: - _LIBCPP_ALWAYS_INLINE char_type* eback() const {return __binp_;} - _LIBCPP_ALWAYS_INLINE char_type* gptr() const {return __ninp_;} - _LIBCPP_ALWAYS_INLINE char_type* egptr() const {return __einp_;} + _LIBCPP_INLINE_VISIBILITY char_type* eback() const {return __binp_;} + _LIBCPP_INLINE_VISIBILITY char_type* gptr() const {return __ninp_;} + _LIBCPP_INLINE_VISIBILITY char_type* egptr() const {return __einp_;} inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY void gbump(int __n) { __ninp_ += __n; } @@ -251,14 +251,14 @@ protected: } // 27.6.2.3.3 Put area: - _LIBCPP_ALWAYS_INLINE char_type* pbase() const {return __bout_;} - _LIBCPP_ALWAYS_INLINE char_type* pptr() const {return __nout_;} - _LIBCPP_ALWAYS_INLINE char_type* epptr() const {return __eout_;} + _LIBCPP_INLINE_VISIBILITY char_type* pbase() const {return __bout_;} + _LIBCPP_INLINE_VISIBILITY char_type* pptr() const {return __nout_;} + _LIBCPP_INLINE_VISIBILITY char_type* epptr() const {return __eout_;} inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY void pbump(int __n) { __nout_ += __n; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY void __pbump(streamsize __n) { __nout_ += __n; } inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY diff --git a/include/support/android/locale_bionic.h b/include/support/android/locale_bionic.h index d638757fd..50fcf5c36 100644 --- a/include/support/android/locale_bionic.h +++ b/include/support/android/locale_bionic.h @@ -40,18 +40,18 @@ extern "C" { extern "C" { #endif -inline _LIBCPP_ALWAYS_INLINE float strtof_l(const char* __nptr, char** __endptr, - locale_t) { +inline _LIBCPP_INLINE_VISIBILITY float strtof_l(const char* __nptr, char** __endptr, + locale_t) { return ::strtof(__nptr, __endptr); } -inline _LIBCPP_ALWAYS_INLINE double strtod_l(const char* __nptr, - char** __endptr, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY double strtod_l(const char* __nptr, + char** __endptr, locale_t) { return ::strtod(__nptr, __endptr); } -inline _LIBCPP_ALWAYS_INLINE long strtol_l(const char* __nptr, char** __endptr, - int __base, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY long strtol_l(const char* __nptr, char** __endptr, + int __base, locale_t) { return ::strtol(__nptr, __endptr, __base); } diff --git a/include/support/xlocale/__posix_l_fallback.h b/include/support/xlocale/__posix_l_fallback.h index c893a6731..b9a0939f8 100644 --- a/include/support/xlocale/__posix_l_fallback.h +++ b/include/support/xlocale/__posix_l_fallback.h @@ -20,141 +20,141 @@ extern "C" { #endif -inline _LIBCPP_ALWAYS_INLINE int isalnum_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isalnum_l(int c, locale_t) { return ::isalnum(c); } -inline _LIBCPP_ALWAYS_INLINE int isalpha_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isalpha_l(int c, locale_t) { return ::isalpha(c); } -inline _LIBCPP_ALWAYS_INLINE int isblank_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isblank_l(int c, locale_t) { return ::isblank(c); } -inline _LIBCPP_ALWAYS_INLINE int iscntrl_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iscntrl_l(int c, locale_t) { return ::iscntrl(c); } -inline _LIBCPP_ALWAYS_INLINE int isdigit_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isdigit_l(int c, locale_t) { return ::isdigit(c); } -inline _LIBCPP_ALWAYS_INLINE int isgraph_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isgraph_l(int c, locale_t) { return ::isgraph(c); } -inline _LIBCPP_ALWAYS_INLINE int islower_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int islower_l(int c, locale_t) { return ::islower(c); } -inline _LIBCPP_ALWAYS_INLINE int isprint_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isprint_l(int c, locale_t) { return ::isprint(c); } -inline _LIBCPP_ALWAYS_INLINE int ispunct_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int ispunct_l(int c, locale_t) { return ::ispunct(c); } -inline _LIBCPP_ALWAYS_INLINE int isspace_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isspace_l(int c, locale_t) { return ::isspace(c); } -inline _LIBCPP_ALWAYS_INLINE int isupper_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isupper_l(int c, locale_t) { return ::isupper(c); } -inline _LIBCPP_ALWAYS_INLINE int isxdigit_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isxdigit_l(int c, locale_t) { return ::isxdigit(c); } -inline _LIBCPP_ALWAYS_INLINE int iswalnum_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswalnum_l(wint_t c, locale_t) { return ::iswalnum(c); } -inline _LIBCPP_ALWAYS_INLINE int iswalpha_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswalpha_l(wint_t c, locale_t) { return ::iswalpha(c); } -inline _LIBCPP_ALWAYS_INLINE int iswblank_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswblank_l(wint_t c, locale_t) { return ::iswblank(c); } -inline _LIBCPP_ALWAYS_INLINE int iswcntrl_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswcntrl_l(wint_t c, locale_t) { return ::iswcntrl(c); } -inline _LIBCPP_ALWAYS_INLINE int iswdigit_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswdigit_l(wint_t c, locale_t) { return ::iswdigit(c); } -inline _LIBCPP_ALWAYS_INLINE int iswgraph_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswgraph_l(wint_t c, locale_t) { return ::iswgraph(c); } -inline _LIBCPP_ALWAYS_INLINE int iswlower_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswlower_l(wint_t c, locale_t) { return ::iswlower(c); } -inline _LIBCPP_ALWAYS_INLINE int iswprint_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswprint_l(wint_t c, locale_t) { return ::iswprint(c); } -inline _LIBCPP_ALWAYS_INLINE int iswpunct_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswpunct_l(wint_t c, locale_t) { return ::iswpunct(c); } -inline _LIBCPP_ALWAYS_INLINE int iswspace_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswspace_l(wint_t c, locale_t) { return ::iswspace(c); } -inline _LIBCPP_ALWAYS_INLINE int iswupper_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswupper_l(wint_t c, locale_t) { return ::iswupper(c); } -inline _LIBCPP_ALWAYS_INLINE int iswxdigit_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswxdigit_l(wint_t c, locale_t) { return ::iswxdigit(c); } -inline _LIBCPP_ALWAYS_INLINE int toupper_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int toupper_l(int c, locale_t) { return ::toupper(c); } -inline _LIBCPP_ALWAYS_INLINE int tolower_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int tolower_l(int c, locale_t) { return ::tolower(c); } -inline _LIBCPP_ALWAYS_INLINE wint_t towupper_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY wint_t towupper_l(wint_t c, locale_t) { return ::towupper(c); } -inline _LIBCPP_ALWAYS_INLINE wint_t towlower_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY wint_t towlower_l(wint_t c, locale_t) { return ::towlower(c); } -inline _LIBCPP_ALWAYS_INLINE int strcoll_l(const char *s1, const char *s2, - locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int strcoll_l(const char *s1, const char *s2, + locale_t) { return ::strcoll(s1, s2); } -inline _LIBCPP_ALWAYS_INLINE size_t strxfrm_l(char *dest, const char *src, - size_t n, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY size_t strxfrm_l(char *dest, const char *src, + size_t n, locale_t) { return ::strxfrm(dest, src, n); } -inline _LIBCPP_ALWAYS_INLINE size_t strftime_l(char *s, size_t max, - const char *format, - const struct tm *tm, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY size_t strftime_l(char *s, size_t max, + const char *format, + const struct tm *tm, locale_t) { return ::strftime(s, max, format, tm); } -inline _LIBCPP_ALWAYS_INLINE int wcscoll_l(const wchar_t *ws1, - const wchar_t *ws2, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int wcscoll_l(const wchar_t *ws1, + const wchar_t *ws2, locale_t) { return ::wcscoll(ws1, ws2); } -inline _LIBCPP_ALWAYS_INLINE size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, - size_t n, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, + size_t n, locale_t) { return ::wcsxfrm(dest, src, n); } diff --git a/include/support/xlocale/__strtonum_fallback.h b/include/support/xlocale/__strtonum_fallback.h index 4ae3918b3..50b4db354 100644 --- a/include/support/xlocale/__strtonum_fallback.h +++ b/include/support/xlocale/__strtonum_fallback.h @@ -20,43 +20,43 @@ extern "C" { #endif -inline _LIBCPP_ALWAYS_INLINE float strtof_l(const char *nptr, - char **endptr, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY float strtof_l(const char *nptr, + char **endptr, locale_t) { return ::strtof(nptr, endptr); } -inline _LIBCPP_ALWAYS_INLINE double strtod_l(const char *nptr, - char **endptr, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY double strtod_l(const char *nptr, + char **endptr, locale_t) { return ::strtod(nptr, endptr); } -inline _LIBCPP_ALWAYS_INLINE long double strtold_l(const char *nptr, - char **endptr, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY long double strtold_l(const char *nptr, + char **endptr, locale_t) { return ::strtold(nptr, endptr); } -inline _LIBCPP_ALWAYS_INLINE long long +inline _LIBCPP_INLINE_VISIBILITY long long strtoll_l(const char *nptr, char **endptr, int base, locale_t) { return ::strtoll(nptr, endptr, base); } -inline _LIBCPP_ALWAYS_INLINE unsigned long long +inline _LIBCPP_INLINE_VISIBILITY unsigned long long strtoull_l(const char *nptr, char **endptr, int base, locale_t) { return ::strtoull(nptr, endptr, base); } -inline _LIBCPP_ALWAYS_INLINE long long +inline _LIBCPP_INLINE_VISIBILITY long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, int base, locale_t) { return ::wcstoll(nptr, endptr, base); } -inline _LIBCPP_ALWAYS_INLINE unsigned long long +inline _LIBCPP_INLINE_VISIBILITY unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr, int base, locale_t) { return ::wcstoull(nptr, endptr, base); } -inline _LIBCPP_ALWAYS_INLINE long double wcstold_l(const wchar_t *nptr, - wchar_t **endptr, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY long double wcstold_l(const wchar_t *nptr, + wchar_t **endptr, locale_t) { return ::wcstold(nptr, endptr); } diff --git a/include/system_error b/include/system_error index f5d8d1145..917c71029 100644 --- a/include/system_error +++ b/include/system_error @@ -203,7 +203,7 @@ public: defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) error_category() _NOEXCEPT; #else - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 error_category() _NOEXCEPT _LIBCPP_DEFAULT #endif private: @@ -217,13 +217,13 @@ public: virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT; virtual string message(int __ev) const = 0; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool operator==(const error_category& __rhs) const _NOEXCEPT {return this == &__rhs;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool operator!=(const error_category& __rhs) const _NOEXCEPT {return !(*this == __rhs);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool operator< (const error_category& __rhs) const _NOEXCEPT {return this < &__rhs;} friend class _LIBCPP_HIDDEN __do_message; @@ -244,21 +244,21 @@ class _LIBCPP_TYPE_VIS error_condition int __val_; const error_category* __cat_; public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_condition() _NOEXCEPT : __val_(0), __cat_(&generic_category()) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_condition(int __val, const error_category& __cat) _NOEXCEPT : __val_(__val), __cat_(&__cat) {} template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_condition(_Ep __e, typename enable_if::value>::type* = 0 ) _NOEXCEPT {*this = make_error_condition(__e);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void assign(int __val, const error_category& __cat) _NOEXCEPT { __val_ = __val; @@ -266,7 +266,7 @@ public: } template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY typename enable_if < is_error_condition_enum<_Ep>::value, @@ -275,21 +275,21 @@ public: operator=(_Ep __e) _NOEXCEPT {*this = make_error_condition(__e); return *this;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT { __val_ = 0; __cat_ = &generic_category(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int value() const _NOEXCEPT {return __val_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const error_category& category() const _NOEXCEPT {return *__cat_;} string message() const; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __val_ != 0;} }; @@ -316,21 +316,21 @@ class _LIBCPP_TYPE_VIS error_code int __val_; const error_category* __cat_; public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_code() _NOEXCEPT : __val_(0), __cat_(&system_category()) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_code(int __val, const error_category& __cat) _NOEXCEPT : __val_(__val), __cat_(&__cat) {} template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_code(_Ep __e, typename enable_if::value>::type* = 0 ) _NOEXCEPT {*this = make_error_code(__e);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void assign(int __val, const error_category& __cat) _NOEXCEPT { __val_ = __val; @@ -338,7 +338,7 @@ public: } template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY typename enable_if < is_error_code_enum<_Ep>::value, @@ -347,26 +347,26 @@ public: operator=(_Ep __e) _NOEXCEPT {*this = make_error_code(__e); return *this;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT { __val_ = 0; __cat_ = &system_category(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int value() const _NOEXCEPT {return __val_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const error_category& category() const _NOEXCEPT {return *__cat_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_condition default_error_condition() const _NOEXCEPT {return __cat_->default_error_condition(__val_);} string message() const; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __val_ != 0;} }; @@ -472,7 +472,7 @@ public: system_error(int __ev, const error_category& __ecat); ~system_error() _NOEXCEPT; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const error_code& code() const _NOEXCEPT {return __ec_;} private: diff --git a/include/typeinfo b/include/typeinfo index 74d94e9e3..f32ea6e76 100644 --- a/include/typeinfo +++ b/include/typeinfo @@ -226,7 +226,7 @@ public: #endif // defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) _LIBCPP_BEGIN_NAMESPACE_STD -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_cast() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/vector b/include/vector index 74c423ef2..0f5006f37 100644 --- a/include/vector +++ b/include/vector @@ -295,7 +295,7 @@ template class __vector_base_common { protected: - _LIBCPP_ALWAYS_INLINE __vector_base_common() {} + _LIBCPP_INLINE_VISIBILITY __vector_base_common() {} _LIBCPP_NORETURN void __throw_length_error() const; _LIBCPP_NORETURN void __throw_out_of_range() const; }; diff --git a/src/support/win32/thread_win32.cpp b/src/support/win32/thread_win32.cpp index 3f479443e..471049429 100644 --- a/src/support/win32/thread_win32.cpp +++ b/src/support/win32/thread_win32.cpp @@ -138,7 +138,7 @@ int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) } // Execute Once -static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK +static inline _LIBCPP_INLINE_VISIBILITY BOOL CALLBACK __libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter, PVOID *__context) { @@ -178,7 +178,7 @@ struct __libcpp_beginthreadex_thunk_data void *__arg; }; -static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI +static inline _LIBCPP_INLINE_VISIBILITY unsigned WINAPI __libcpp_beginthreadex_thunk(void *__raw_data) { auto *__data = -- GitLab From 1f655099cffdec47f66743514b19f0071795d30b Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Thu, 5 Jul 2018 17:44:12 +0000 Subject: [PATCH 013/495] Fix HTML blunder git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336381 91177308-0d34-0410-b5e6-96231b3b80d8 --- www/cxx2a_status.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/cxx2a_status.html b/www/cxx2a_status.html index 9f195c35d..6b486bb62 100644 --- a/www/cxx2a_status.html +++ b/www/cxx2a_status.html @@ -210,7 +210,7 @@ 3067recursive_directory_iterator::pop must invalidateRapperswilNothing to do 3071[networking.ts] read_until still refers to "input sequence"RapperswilNothing to do 3074Non-member functions for valarray should only deduce from the valarrayRapperswil - 3076basic_string CTAD ambiguityRapperswilComplete + 3076basic_string CTAD ambiguityRapperswilComplete 3079LWG 2935 forgot to fix the existing_p overloads of create_directoryRapperswil 3080Floating point from_chars pattern specification breaks round-trippingRapperswil 3083What should ios::iword(-1) do?RapperswilNothing to do -- GitLab From 4e7ffcaae6a2ea71bb43d2aaaac81c752f394612 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Thu, 5 Jul 2018 18:41:50 +0000 Subject: [PATCH 014/495] Revert "[libc++] Replace uses of _LIBCPP_ALWAYS_INLINE by _LIBCPP_INLINE_VISIBILITY" This reverts commit r336369. The commit had two problems: 1. __pbump was marked as _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY instead of _LIBCPP_INLINE_VISIBILITY, which lead to two symbols being added in the dylib and the check-cxx-abilist failing. 2. The LLDB tests started failing because they undefine `_LIBCPP_INLINE_VISIBILITY`. I need to figure out why they do that and fix the tests before we can go forward with this change. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336382 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/DesignDocs/VisibilityMacros.rst | 8 +- include/__bsd_locale_fallbacks.h | 22 +-- include/__config | 16 +- include/__locale | 168 ++++++++--------- include/__nullptr | 16 +- include/any | 6 +- include/cmath | 12 +- include/codecvt | 36 ++-- include/exception | 4 +- include/experimental/dynarray | 2 +- include/experimental/filesystem | 12 +- include/functional | 2 +- include/future | 2 +- include/initializer_list | 10 +- include/ios | 34 ++-- include/locale | 176 +++++++++--------- include/math.h | 24 +-- include/memory | 6 +- include/new | 2 +- include/ostream | 4 +- include/regex | 2 +- include/stdexcept | 16 +- include/streambuf | 14 +- include/support/android/locale_bionic.h | 12 +- include/support/xlocale/__posix_l_fallback.h | 78 ++++---- include/support/xlocale/__strtonum_fallback.h | 24 +-- include/system_error | 48 ++--- include/typeinfo | 2 +- include/vector | 2 +- src/support/win32/thread_win32.cpp | 4 +- 30 files changed, 387 insertions(+), 377 deletions(-) diff --git a/docs/DesignDocs/VisibilityMacros.rst b/docs/DesignDocs/VisibilityMacros.rst index 69a09974a..993ce2cca 100644 --- a/docs/DesignDocs/VisibilityMacros.rst +++ b/docs/DesignDocs/VisibilityMacros.rst @@ -41,10 +41,10 @@ Visibility Macros library and has an empty definition otherwise. **_LIBCPP_INLINE_VISIBILITY** - Mark a function as not being part of the ABI of any final linked image that - uses it, and also as being internal to each TU that uses that function. In - other words, the address of a function marked with this attribute is not - guaranteed to be the same across translation units. + Mark a function as hidden and force inlining whenever possible. + +**_LIBCPP_ALWAYS_INLINE** + A synonym for `_LIBCPP_INLINE_VISIBILITY` **_LIBCPP_TYPE_VIS** Mark a type's typeinfo, vtable and members as having default visibility. diff --git a/include/__bsd_locale_fallbacks.h b/include/__bsd_locale_fallbacks.h index 3097b0141..5e9e09483 100644 --- a/include/__bsd_locale_fallbacks.h +++ b/include/__bsd_locale_fallbacks.h @@ -24,28 +24,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l) { __libcpp_locale_guard __current(__l); return MB_CUR_MAX; } -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE wint_t __libcpp_btowc_l(int __c, locale_t __l) { __libcpp_locale_guard __current(__l); return btowc(__c); } -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE int __libcpp_wctob_l(wint_t __c, locale_t __l) { __libcpp_locale_guard __current(__l); return wctob(__c); } -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc, size_t __len, mbstate_t *__ps, locale_t __l) { @@ -53,14 +53,14 @@ size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc, return wcsnrtombs(__dest, __src, __nwc, __len, __ps); } -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE size_t __libcpp_wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l) { __libcpp_locale_guard __current(__l); return wcrtomb(__s, __wc, __ps); } -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms, size_t __len, mbstate_t *__ps, locale_t __l) { @@ -68,7 +68,7 @@ size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms, return mbsnrtowcs(__dest, __src, __nms, __len, __ps); } -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) { @@ -76,28 +76,28 @@ size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n, return mbrtowc(__pwc, __s, __n, __ps); } -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE int __libcpp_mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l) { __libcpp_locale_guard __current(__l); return mbtowc(__pwc, __pmb, __max); } -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) { __libcpp_locale_guard __current(__l); return mbrlen(__s, __n, __ps); } -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE lconv *__libcpp_localeconv_l(locale_t __l) { __libcpp_locale_guard __current(__l); return localeconv(); } -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len, mbstate_t *__ps, locale_t __l) { diff --git a/include/__config b/include/__config index 233c2b3ab..52c7142ff 100644 --- a/include/__config +++ b/include/__config @@ -672,9 +672,11 @@ namespace std { #if defined(_LIBCPP_COMPILER_MSVC) # define _LIBCPP_INLINE_VISIBILITY __forceinline +# define _LIBCPP_ALWAYS_INLINE __forceinline # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __forceinline #else # define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__always_inline__)) +# define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__ ((__always_inline__)) #endif @@ -769,6 +771,14 @@ namespace std { # endif #endif +#ifndef _LIBCPP_ALWAYS_INLINE +# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) +# define _LIBCPP_ALWAYS_INLINE __attribute__ ((__visibility__("hidden"), __always_inline__)) +# else +# define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) +# endif +#endif + #ifndef _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__((__visibility__("default"), __always_inline__)) @@ -879,9 +889,9 @@ template struct __static_assert_check {}; # define _LIBCPP_DECLARE_STRONG_ENUM(x) struct _LIBCPP_TYPE_VIS x { enum __lx # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \ __lx __v_; \ - _LIBCPP_INLINE_VISIBILITY x(__lx __v) : __v_(__v) {} \ - _LIBCPP_INLINE_VISIBILITY explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ - _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;} \ + _LIBCPP_ALWAYS_INLINE x(__lx __v) : __v_(__v) {} \ + _LIBCPP_ALWAYS_INLINE explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ + _LIBCPP_ALWAYS_INLINE operator int() const {return __v_;} \ }; #else // _LIBCPP_HAS_NO_STRONG_ENUMS # define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_ENUM_VIS x diff --git a/include/__locale b/include/__locale index f43e7b430..c293b81fb 100644 --- a/include/__locale +++ b/include/__locale @@ -469,7 +469,7 @@ public: static const mask alnum = alpha | digit; static const mask graph = alnum | punct; - _LIBCPP_INLINE_VISIBILITY ctype_base() {} + _LIBCPP_ALWAYS_INLINE ctype_base() {} }; template class _LIBCPP_TEMPLATE_VIS ctype; @@ -482,77 +482,77 @@ class _LIBCPP_TYPE_VIS ctype public: typedef wchar_t char_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit ctype(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE bool is(mask __m, char_type __c) const { return do_is(__m, __c); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const { return do_is(__low, __high, __vec); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* scan_is(mask __m, const char_type* __low, const char_type* __high) const { return do_scan_is(__m, __low, __high); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const { return do_scan_not(__m, __low, __high); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE char_type toupper(char_type __c) const { return do_toupper(__c); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* toupper(char_type* __low, const char_type* __high) const { return do_toupper(__low, __high); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE char_type tolower(char_type __c) const { return do_tolower(__c); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* tolower(char_type* __low, const char_type* __high) const { return do_tolower(__low, __high); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE char_type widen(char __c) const { return do_widen(__c); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char* widen(const char* __low, const char* __high, char_type* __to) const { return do_widen(__low, __high, __to); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE char narrow(char_type __c, char __dfault) const { return do_narrow(__c, __dfault); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const { return do_narrow(__low, __high, __dfault, __to); @@ -587,13 +587,13 @@ public: explicit ctype(const mask* __tab = 0, bool __del = false, size_t __refs = 0); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE bool is(mask __m, char_type __c) const { return isascii(__c) ? (__tab_[static_cast(__c)] & __m) !=0 : false; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const { for (; __low != __high; ++__low, ++__vec) @@ -601,7 +601,7 @@ public: return __low; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* scan_is (mask __m, const char_type* __low, const char_type* __high) const { for (; __low != __high; ++__low) @@ -610,7 +610,7 @@ public: return __low; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const { for (; __low != __high; ++__low) @@ -619,49 +619,49 @@ public: return __low; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE char_type toupper(char_type __c) const { return do_toupper(__c); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* toupper(char_type* __low, const char_type* __high) const { return do_toupper(__low, __high); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE char_type tolower(char_type __c) const { return do_tolower(__c); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char_type* tolower(char_type* __low, const char_type* __high) const { return do_tolower(__low, __high); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE char_type widen(char __c) const { return do_widen(__c); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char* widen(const char* __low, const char* __high, char_type* __to) const { return do_widen(__low, __high, __to); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE char narrow(char_type __c, char __dfault) const { return do_narrow(__c, __dfault); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const char* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const { return do_narrow(__low, __high, __dfault, __to); @@ -674,7 +674,7 @@ public: #else static const size_t table_size = 256; // FIXME: Don't hardcode this. #endif - _LIBCPP_INLINE_VISIBILITY const mask* table() const _NOEXCEPT {return __tab_;} + _LIBCPP_ALWAYS_INLINE const mask* table() const _NOEXCEPT {return __tab_;} static const mask* classic_table() _NOEXCEPT; #if defined(__GLIBC__) || defined(__EMSCRIPTEN__) static const int* __classic_upper_table() _NOEXCEPT; @@ -854,7 +854,7 @@ tolower(_CharT __c, const locale& __loc) class _LIBCPP_TYPE_VIS codecvt_base { public: - _LIBCPP_INLINE_VISIBILITY codecvt_base() {} + _LIBCPP_ALWAYS_INLINE codecvt_base() {} enum result {ok, partial, error, noconv}; }; @@ -874,11 +874,11 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -886,14 +886,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -901,25 +901,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int max_length() const _NOEXCEPT { return do_max_length(); @@ -928,7 +928,7 @@ public: static locale::id id; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {} @@ -963,7 +963,7 @@ public: explicit codecvt(size_t __refs = 0); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -971,14 +971,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -986,25 +986,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int max_length() const _NOEXCEPT { return do_max_length(); @@ -1043,11 +1043,11 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -1055,14 +1055,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -1070,25 +1070,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int max_length() const _NOEXCEPT { return do_max_length(); @@ -1097,7 +1097,7 @@ public: static locale::id id; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {} @@ -1129,11 +1129,11 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -1141,14 +1141,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -1156,25 +1156,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int max_length() const _NOEXCEPT { return do_max_length(); @@ -1183,7 +1183,7 @@ public: static locale::id id; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {} @@ -1210,10 +1210,10 @@ class _LIBCPP_TEMPLATE_VIS codecvt_byname : public codecvt<_InternT, _ExternT, _StateT> { public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt_byname(const char* __nm, size_t __refs = 0) : codecvt<_InternT, _ExternT, _StateT>(__nm, __refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt_byname(const string& __nm, size_t __refs = 0) : codecvt<_InternT, _ExternT, _StateT>(__nm.c_str(), __refs) {} protected: @@ -1244,7 +1244,7 @@ template <> struct __narrow_to_utf8<8> { template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const { @@ -1258,13 +1258,13 @@ template <> struct __narrow_to_utf8<16> : public codecvt { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE __narrow_to_utf8() : codecvt(1) {} ~__narrow_to_utf8(); template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const { @@ -1292,13 +1292,13 @@ template <> struct __narrow_to_utf8<32> : public codecvt { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE __narrow_to_utf8() : codecvt(1) {} ~__narrow_to_utf8(); template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const { @@ -1334,7 +1334,7 @@ template <> struct __widen_from_utf8<8> { template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const { @@ -1348,13 +1348,13 @@ template <> struct __widen_from_utf8<16> : public codecvt { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE __widen_from_utf8() : codecvt(1) {} ~__widen_from_utf8(); template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const { @@ -1382,13 +1382,13 @@ template <> struct __widen_from_utf8<32> : public codecvt { - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE __widen_from_utf8() : codecvt(1) {} ~__widen_from_utf8(); template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const { @@ -1426,11 +1426,11 @@ public: explicit numpunct(size_t __refs = 0); - _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();} - _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();} - _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();} - _LIBCPP_INLINE_VISIBILITY string_type truename() const {return do_truename();} - _LIBCPP_INLINE_VISIBILITY string_type falsename() const {return do_falsename();} + _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} + _LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();} + _LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();} static locale::id id; @@ -1457,11 +1457,11 @@ public: explicit numpunct(size_t __refs = 0); - _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();} - _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();} - _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();} - _LIBCPP_INLINE_VISIBILITY string_type truename() const {return do_truename();} - _LIBCPP_INLINE_VISIBILITY string_type falsename() const {return do_falsename();} + _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} + _LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();} + _LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();} static locale::id id; diff --git a/include/__nullptr b/include/__nullptr index aa3b4d214..a341234f5 100644 --- a/include/__nullptr +++ b/include/__nullptr @@ -27,24 +27,24 @@ struct _LIBCPP_TEMPLATE_VIS nullptr_t struct __nat {int __for_bool_;}; - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {} + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {} + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {} - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;} + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;} template - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR operator _Tp* () const {return 0;} template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE operator _Tp _Up::* () const {return 0;} - friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;} - friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;} + friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;} + friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;} }; -inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);} +inline _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);} #define nullptr _VSTD::__get_nullptr_t() diff --git a/include/any b/include/any index 9bd2f53c5..d7161b0d6 100644 --- a/include/any +++ b/include/any @@ -104,7 +104,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_bad_any_cast() { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -304,7 +304,7 @@ private: __any_imp::_Buffer __buf; }; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void * __call(_Action __a, any * __other = nullptr, type_info const * __info = nullptr, const void* __fallback_info = nullptr) const @@ -312,7 +312,7 @@ private: return __h(__a, this, __other, __info, __fallback_info); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void * __call(_Action __a, any * __other = nullptr, type_info const * __info = nullptr, const void* __fallback_info = nullptr) diff --git a/include/cmath b/include/cmath index ffb1c46c7..917928a1f 100644 --- a/include/cmath +++ b/include/cmath @@ -547,7 +547,7 @@ hypot(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT #endif template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -559,7 +559,7 @@ __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -567,7 +567,7 @@ __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -579,7 +579,7 @@ __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -587,7 +587,7 @@ __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -599,7 +599,7 @@ __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT { diff --git a/include/codecvt b/include/codecvt index 5eb9d1549..46f56acff 100644 --- a/include/codecvt +++ b/include/codecvt @@ -86,7 +86,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -121,7 +121,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -156,7 +156,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -186,11 +186,11 @@ class _LIBCPP_TEMPLATE_VIS codecvt_utf8 : public __codecvt_utf8<_Elem> { public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt_utf8(size_t __refs = 0) : __codecvt_utf8<_Elem>(__refs, _Maxcode, _Mode) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~codecvt_utf8() {} }; @@ -209,7 +209,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -244,7 +244,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -279,7 +279,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -314,7 +314,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -349,7 +349,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -384,7 +384,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -414,11 +414,11 @@ class _LIBCPP_TEMPLATE_VIS codecvt_utf16 : public __codecvt_utf16<_Elem, _Mode & little_endian> { public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt_utf16(size_t __refs = 0) : __codecvt_utf16<_Elem, _Mode & little_endian>(__refs, _Maxcode, _Mode) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~codecvt_utf16() {} }; @@ -437,7 +437,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -472,7 +472,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -507,7 +507,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -537,11 +537,11 @@ class _LIBCPP_TEMPLATE_VIS codecvt_utf8_utf16 : public __codecvt_utf8_utf16<_Elem> { public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit codecvt_utf8_utf16(size_t __refs = 0) : __codecvt_utf8_utf16<_Elem>(__refs, _Maxcode, _Mode) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~codecvt_utf8_utf16() {} }; diff --git a/include/exception b/include/exception index b517486b5..79bd6ac2a 100644 --- a/include/exception +++ b/include/exception @@ -259,7 +259,7 @@ struct __throw_with_nested; template struct __throw_with_nested<_Tp, _Up, true> { - _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void + _LIBCPP_NORETURN static inline _LIBCPP_ALWAYS_INLINE void #ifndef _LIBCPP_CXX03_LANG __do_throw(_Tp&& __t) #else @@ -272,7 +272,7 @@ struct __throw_with_nested<_Tp, _Up, true> { template struct __throw_with_nested<_Tp, _Up, false> { - _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void + _LIBCPP_NORETURN static inline _LIBCPP_ALWAYS_INLINE void #ifndef _LIBCPP_CXX03_LANG __do_throw(_Tp&& __t) #else diff --git a/include/experimental/dynarray b/include/experimental/dynarray index a60c87c3f..cebfc208d 100644 --- a/include/experimental/dynarray +++ b/include/experimental/dynarray @@ -133,7 +133,7 @@ public: private: size_t __size_; value_type * __base_; - _LIBCPP_INLINE_VISIBILITY dynarray () noexcept : __size_(0), __base_(nullptr) {} + _LIBCPP_ALWAYS_INLINE dynarray () noexcept : __size_(0), __base_(nullptr) {} static inline _LIBCPP_INLINE_VISIBILITY value_type* __allocate(size_t __count) { diff --git a/include/experimental/filesystem b/include/experimental/filesystem index 1ca179699..f29e23e18 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -470,23 +470,23 @@ public: file_status& operator=(file_status&&) _NOEXCEPT = default; // observers - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE file_type type() const _NOEXCEPT { return __ft_; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE perms permissions() const _NOEXCEPT { return __prms_; } // modifiers - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void type(file_type __ft) _NOEXCEPT { __ft_ = __ft; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void permissions(perms __p) _NOEXCEPT { __prms_ = __p; } @@ -1106,7 +1106,7 @@ private: string_type __pn_; }; -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE void swap(path& __lhs, path& __rhs) _NOEXCEPT { __lhs.swap(__rhs); } @@ -1298,7 +1298,7 @@ private: }; template -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE #ifndef _LIBCPP_NO_EXCEPTIONS void __throw_filesystem_error(_Args && ...__args) { diff --git a/include/functional b/include/functional index 80261895e..bb0bdf151 100644 --- a/include/functional +++ b/include/functional @@ -1399,7 +1399,7 @@ public: #endif }; -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_bad_function_call() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/future b/include/future index 528091b04..536574e75 100644 --- a/include/future +++ b/include/future @@ -514,7 +514,7 @@ public: virtual ~future_error() _NOEXCEPT; }; -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE #ifndef _LIBCPP_NO_EXCEPTIONS _LIBCPP_AVAILABILITY_FUTURE_ERROR #endif diff --git a/include/initializer_list b/include/initializer_list index b934637b8..8c234aaaa 100644 --- a/include/initializer_list +++ b/include/initializer_list @@ -61,7 +61,7 @@ class _LIBCPP_TEMPLATE_VIS initializer_list const _Ep* __begin_; size_t __size_; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR_AFTER_CXX11 initializer_list(const _Ep* __b, size_t __s) _NOEXCEPT : __begin_(__b), @@ -76,19 +76,19 @@ public: typedef const _Ep* iterator; typedef const _Ep* const_iterator; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR_AFTER_CXX11 initializer_list() _NOEXCEPT : __begin_(nullptr), __size_(0) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR_AFTER_CXX11 size_t size() const _NOEXCEPT {return __size_;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR_AFTER_CXX11 const _Ep* begin() const _NOEXCEPT {return __begin_;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR_AFTER_CXX11 const _Ep* end() const _NOEXCEPT {return __begin_ + __size_;} }; diff --git a/include/ios b/include/ios index 040b2d4e0..6e32d0fe6 100644 --- a/include/ios +++ b/include/ios @@ -337,9 +337,9 @@ protected: } void init(void* __sb); - _LIBCPP_INLINE_VISIBILITY void* rdbuf() const {return __rdbuf_;} + _LIBCPP_ALWAYS_INLINE void* rdbuf() const {return __rdbuf_;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void rdbuf(void* __sb) { __rdbuf_ = __sb; @@ -351,7 +351,7 @@ protected: void move(ios_base&); void swap(ios_base&) _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void set_rdbuf(void* __sb) { __rdbuf_ = __sb; @@ -599,26 +599,26 @@ public: // we give it internal linkage. #if defined(_LIBCPP_CXX03_LANG) - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE operator __cxx03_bool::__bool_type() const { return !fail() ? &__cxx03_bool::__true_value : nullptr; } #else - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_EXPLICIT operator bool() const {return !fail();} #endif - _LIBCPP_INLINE_VISIBILITY bool operator!() const {return fail();} - _LIBCPP_INLINE_VISIBILITY iostate rdstate() const {return ios_base::rdstate();} - _LIBCPP_INLINE_VISIBILITY void clear(iostate __state = goodbit) {ios_base::clear(__state);} - _LIBCPP_INLINE_VISIBILITY void setstate(iostate __state) {ios_base::setstate(__state);} - _LIBCPP_INLINE_VISIBILITY bool good() const {return ios_base::good();} - _LIBCPP_INLINE_VISIBILITY bool eof() const {return ios_base::eof();} - _LIBCPP_INLINE_VISIBILITY bool fail() const {return ios_base::fail();} - _LIBCPP_INLINE_VISIBILITY bool bad() const {return ios_base::bad();} + _LIBCPP_ALWAYS_INLINE bool operator!() const {return fail();} + _LIBCPP_ALWAYS_INLINE iostate rdstate() const {return ios_base::rdstate();} + _LIBCPP_ALWAYS_INLINE void clear(iostate __state = goodbit) {ios_base::clear(__state);} + _LIBCPP_ALWAYS_INLINE void setstate(iostate __state) {ios_base::setstate(__state);} + _LIBCPP_ALWAYS_INLINE bool good() const {return ios_base::good();} + _LIBCPP_ALWAYS_INLINE bool eof() const {return ios_base::eof();} + _LIBCPP_ALWAYS_INLINE bool fail() const {return ios_base::fail();} + _LIBCPP_ALWAYS_INLINE bool bad() const {return ios_base::bad();} - _LIBCPP_INLINE_VISIBILITY iostate exceptions() const {return ios_base::exceptions();} - _LIBCPP_INLINE_VISIBILITY void exceptions(iostate __iostate) {ios_base::exceptions(__iostate);} + _LIBCPP_ALWAYS_INLINE iostate exceptions() const {return ios_base::exceptions();} + _LIBCPP_ALWAYS_INLINE void exceptions(iostate __iostate) {ios_base::exceptions(__iostate);} // 27.5.4.1 Constructor/destructor: _LIBCPP_INLINE_VISIBILITY @@ -652,7 +652,7 @@ public: char_type widen(char __c) const; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE basic_ios() {// purposefully does no initialization } _LIBCPP_INLINE_VISIBILITY @@ -661,7 +661,7 @@ protected: _LIBCPP_INLINE_VISIBILITY void move(basic_ios& __rhs); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void move(basic_ios&& __rhs) {move(__rhs);} #endif _LIBCPP_INLINE_VISIBILITY diff --git a/include/locale b/include/locale index e240799f3..52885b768 100644 --- a/include/locale +++ b/include/locale @@ -573,81 +573,81 @@ public: typedef _CharT char_type; typedef _InputIterator iter_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit num_get(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { @@ -657,7 +657,7 @@ public: static locale::id id; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~num_get() {} template @@ -1261,60 +1261,60 @@ public: typedef _CharT char_type; typedef _OutputIterator iter_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit num_put(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { @@ -1324,7 +1324,7 @@ public: static locale::id id; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~num_put() {} virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, @@ -1738,7 +1738,7 @@ protected: virtual const string_type& __x() const; virtual const string_type& __X() const; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~__time_get_c_storage() {} }; @@ -1770,52 +1770,52 @@ public: typedef time_base::dateorder dateorder; typedef basic_string string_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit time_get(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE dateorder date_order() const { return this->do_date_order(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_time(__b, __e, __iob, __err, __tm); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_date(__b, __e, __iob, __err, __tm); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_weekday(__b, __e, __iob, __err, __tm); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_monthname(__b, __e, __iob, __err, __tm); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_year(__b, __e, __iob, __err, __tm); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm *__tm, char __fmt, char __mod = 0) const @@ -1830,7 +1830,7 @@ public: static locale::id id; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~time_get() {} virtual dateorder do_date_order() const; @@ -2399,7 +2399,7 @@ protected: explicit __time_get_storage(const char* __nm); explicit __time_get_storage(const string& __nm); - _LIBCPP_INLINE_VISIBILITY ~__time_get_storage() {} + _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {} time_base::dateorder __do_date_order() const; @@ -2458,7 +2458,7 @@ class _LIBCPP_TYPE_VIS __time_put { locale_t __loc_; protected: - _LIBCPP_INLINE_VISIBILITY __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} + _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} __time_put(const char* __nm); __time_put(const string& __nm); ~__time_put(); @@ -2477,14 +2477,14 @@ public: typedef _CharT char_type; typedef _OutputIterator iter_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit time_put(size_t __refs = 0) : locale::facet(__refs) {} iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) const; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, char __fmt, char __mod = 0) const { @@ -2494,16 +2494,16 @@ public: static locale::id id; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~time_put() {} virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit time_put(const char* __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit time_put(const string& __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {} @@ -2572,16 +2572,16 @@ class _LIBCPP_TEMPLATE_VIS time_put_byname : public time_put<_CharT, _OutputIterator> { public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit time_put_byname(const char* __nm, size_t __refs = 0) : time_put<_CharT, _OutputIterator>(__nm, __refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit time_put_byname(const string& __nm, size_t __refs = 0) : time_put<_CharT, _OutputIterator>(__nm, __refs) {} protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~time_put_byname() {} }; @@ -2596,7 +2596,7 @@ public: enum part {none, space, symbol, sign, value}; struct pattern {char field[4];}; - _LIBCPP_INLINE_VISIBILITY money_base() {} + _LIBCPP_ALWAYS_INLINE money_base() {} }; // moneypunct @@ -2610,25 +2610,25 @@ public: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();} - _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();} - _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();} - _LIBCPP_INLINE_VISIBILITY string_type curr_symbol() const {return do_curr_symbol();} - _LIBCPP_INLINE_VISIBILITY string_type positive_sign() const {return do_positive_sign();} - _LIBCPP_INLINE_VISIBILITY string_type negative_sign() const {return do_negative_sign();} - _LIBCPP_INLINE_VISIBILITY int frac_digits() const {return do_frac_digits();} - _LIBCPP_INLINE_VISIBILITY pattern pos_format() const {return do_pos_format();} - _LIBCPP_INLINE_VISIBILITY pattern neg_format() const {return do_neg_format();} + _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} + _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();} + _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();} + _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();} + _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();} + _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();} + _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();} static locale::id id; static const bool intl = _International; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~moneypunct() {} virtual char_type do_decimal_point() const {return numeric_limits::max();} @@ -2668,16 +2668,16 @@ public: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit moneypunct_byname(const char* __nm, size_t __refs = 0) : moneypunct<_CharT, _International>(__refs) {init(__nm);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit moneypunct_byname(const string& __nm, size_t __refs = 0) : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());} protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~moneypunct_byname() {} virtual char_type do_decimal_point() const {return __decimal_point_;} @@ -2723,7 +2723,7 @@ protected: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_INLINE_VISIBILITY __money_get() {} + _LIBCPP_ALWAYS_INLINE __money_get() {} static void __gather_info(bool __intl, const locale& __loc, money_base::pattern& __pat, char_type& __dp, @@ -2781,18 +2781,18 @@ public: typedef _InputIterator iter_type; typedef basic_string string_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit money_get(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { return do_get(__b, __e, __intl, __iob, __err, __v); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { @@ -2803,7 +2803,7 @@ public: protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~money_get() {} virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl, @@ -3163,7 +3163,7 @@ protected: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_INLINE_VISIBILITY __money_put() {} + _LIBCPP_ALWAYS_INLINE __money_put() {} static void __gather_info(bool __intl, bool __neg, const locale& __loc, money_base::pattern& __pat, char_type& __dp, @@ -3339,18 +3339,18 @@ public: typedef _OutputIterator iter_type; typedef basic_string string_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit money_put(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { return do_put(__s, __intl, __iob, __fl, __units); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { @@ -3360,7 +3360,7 @@ public: static locale::id id; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~money_put() {} virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, @@ -3489,7 +3489,7 @@ class _LIBCPP_TYPE_VIS messages_base public: typedef ptrdiff_t catalog; - _LIBCPP_INLINE_VISIBILITY messages_base() {} + _LIBCPP_ALWAYS_INLINE messages_base() {} }; template @@ -3501,24 +3501,24 @@ public: typedef _CharT char_type; typedef basic_string<_CharT> string_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit messages(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE catalog open(const basic_string& __nm, const locale& __loc) const { return do_open(__nm, __loc); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE string_type get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { return do_get(__c, __set, __msgid, __dflt); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void close(catalog __c) const { do_close(__c); @@ -3527,7 +3527,7 @@ public: static locale::id id; protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~messages() {} virtual catalog do_open(const basic_string&, const locale&) const; @@ -3600,16 +3600,16 @@ public: typedef messages_base::catalog catalog; typedef basic_string<_CharT> string_type; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit messages_byname(const char*, size_t __refs = 0) : messages<_CharT>(__refs) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE explicit messages_byname(const string&, size_t __refs = 0) : messages<_CharT>(__refs) {} protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE ~messages_byname() {} }; @@ -3637,43 +3637,43 @@ private: wstring_convert(const wstring_convert& __wc); wstring_convert& operator=(const wstring_convert& __wc); public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE wstring_convert(_Codecvt* __pcvt, state_type __state); _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err = wide_string()); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE wstring_convert(wstring_convert&& __wc); #endif ~wstring_convert(); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE wide_string from_bytes(char __byte) {return from_bytes(&__byte, &__byte+1);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE wide_string from_bytes(const char* __ptr) {return from_bytes(__ptr, __ptr + char_traits::length(__ptr));} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE wide_string from_bytes(const byte_string& __str) {return from_bytes(__str.data(), __str.data() + __str.size());} wide_string from_bytes(const char* __first, const char* __last); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE byte_string to_bytes(_Elem __wchar) {return to_bytes(&__wchar, &__wchar+1);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE byte_string to_bytes(const _Elem* __wptr) {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE byte_string to_bytes(const wide_string& __wstr) {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());} byte_string to_bytes(const _Elem* __first, const _Elem* __last); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE size_t converted() const _NOEXCEPT {return __cvtcount_;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE state_type state() const {return __cvtstate_;} }; diff --git a/include/math.h b/include/math.h index 3cc72aa27..658ba93be 100644 --- a/include/math.h +++ b/include/math.h @@ -314,7 +314,7 @@ extern "C++" { #ifdef signbit template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_signbit(_A1 __lcpp_x) _NOEXCEPT { @@ -376,7 +376,7 @@ signbit(_A1) _NOEXCEPT #ifdef fpclassify template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE int __libcpp_fpclassify(_A1 __lcpp_x) _NOEXCEPT { @@ -422,7 +422,7 @@ fpclassify(_A1 __lcpp_x) _NOEXCEPT #ifdef isfinite template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT { @@ -456,7 +456,7 @@ isfinite(_A1) _NOEXCEPT #ifdef isinf template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT { @@ -504,7 +504,7 @@ isinf(long double __lcpp_x) _NOEXCEPT { return __libcpp_isinf(__lcpp_x); } #ifdef isnan template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT { @@ -548,7 +548,7 @@ isnan(long double __lcpp_x) _NOEXCEPT { return __libcpp_isnan(__lcpp_x); } #ifdef isnormal template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_isnormal(_A1 __lcpp_x) _NOEXCEPT { @@ -578,7 +578,7 @@ isnormal(_A1 __lcpp_x) _NOEXCEPT #ifdef isgreater template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_isgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -608,7 +608,7 @@ isgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef isgreaterequal template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_isgreaterequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -638,7 +638,7 @@ isgreaterequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef isless template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_isless(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -668,7 +668,7 @@ isless(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef islessequal template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_islessequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -698,7 +698,7 @@ islessequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef islessgreater template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_islessgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -728,7 +728,7 @@ islessgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef isunordered template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_ALWAYS_INLINE bool __libcpp_isunordered(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { diff --git a/include/memory b/include/memory index fd830d7ed..31d4e4fac 100644 --- a/include/memory +++ b/include/memory @@ -679,7 +679,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE _ValueType __libcpp_relaxed_load(_ValueType const* __value) { #if !defined(_LIBCPP_HAS_NO_THREADS) && \ defined(__ATOMIC_RELAXED) && \ @@ -691,7 +691,7 @@ _ValueType __libcpp_relaxed_load(_ValueType const* __value) { } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_ALWAYS_INLINE _ValueType __libcpp_acquire_load(_ValueType const* __value) { #if !defined(_LIBCPP_HAS_NO_THREADS) && \ defined(__ATOMIC_ACQUIRE) && \ @@ -3483,7 +3483,7 @@ public: virtual const char* what() const _NOEXCEPT; }; -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_bad_weak_ptr() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/new b/include/new index b5dc05542..e42ffad27 100644 --- a/include/new +++ b/include/new @@ -281,7 +281,7 @@ inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate(void* __ptr, size_t __ } #ifdef _LIBCPP_BAD_ARRAY_LENGTH_DEFINED -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE #ifndef _LIBCPP_NO_EXCEPTIONS _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH #endif diff --git a/include/ostream b/include/ostream index 5404e0dca..197636eac 100644 --- a/include/ostream +++ b/include/ostream @@ -232,7 +232,7 @@ public: basic_ostream& seekp(off_type __off, ios_base::seekdir __dir); protected: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE basic_ostream() {} // extension, intentially does not initialize }; @@ -249,7 +249,7 @@ public: explicit sentry(basic_ostream<_CharT, _Traits>& __os); ~sentry(); - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_EXPLICIT operator bool() const {return __ok_;} }; diff --git a/include/regex b/include/regex index 84aacc029..612fa84ce 100644 --- a/include/regex +++ b/include/regex @@ -968,7 +968,7 @@ public: }; template -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_regex_error() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/stdexcept b/include/stdexcept index 6533497e4..95a96cc07 100644 --- a/include/stdexcept +++ b/include/stdexcept @@ -185,7 +185,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // in the dylib _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_runtime_error(const char*); -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_logic_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -196,7 +196,7 @@ void __throw_logic_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_domain_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -207,7 +207,7 @@ void __throw_domain_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_invalid_argument(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -218,7 +218,7 @@ void __throw_invalid_argument(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_length_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -229,7 +229,7 @@ void __throw_length_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_out_of_range(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -240,7 +240,7 @@ void __throw_out_of_range(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_range_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -251,7 +251,7 @@ void __throw_range_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_overflow_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -262,7 +262,7 @@ void __throw_overflow_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_underflow_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/streambuf b/include/streambuf index 7887a0502..e409d2106 100644 --- a/include/streambuf +++ b/include/streambuf @@ -236,9 +236,9 @@ protected: void swap(basic_streambuf& __rhs); // 27.6.2.3.2 Get area: - _LIBCPP_INLINE_VISIBILITY char_type* eback() const {return __binp_;} - _LIBCPP_INLINE_VISIBILITY char_type* gptr() const {return __ninp_;} - _LIBCPP_INLINE_VISIBILITY char_type* egptr() const {return __einp_;} + _LIBCPP_ALWAYS_INLINE char_type* eback() const {return __binp_;} + _LIBCPP_ALWAYS_INLINE char_type* gptr() const {return __ninp_;} + _LIBCPP_ALWAYS_INLINE char_type* egptr() const {return __einp_;} inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY void gbump(int __n) { __ninp_ += __n; } @@ -251,14 +251,14 @@ protected: } // 27.6.2.3.3 Put area: - _LIBCPP_INLINE_VISIBILITY char_type* pbase() const {return __bout_;} - _LIBCPP_INLINE_VISIBILITY char_type* pptr() const {return __nout_;} - _LIBCPP_INLINE_VISIBILITY char_type* epptr() const {return __eout_;} + _LIBCPP_ALWAYS_INLINE char_type* pbase() const {return __bout_;} + _LIBCPP_ALWAYS_INLINE char_type* pptr() const {return __nout_;} + _LIBCPP_ALWAYS_INLINE char_type* epptr() const {return __eout_;} inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY void pbump(int __n) { __nout_ += __n; } - _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void __pbump(streamsize __n) { __nout_ += __n; } inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY diff --git a/include/support/android/locale_bionic.h b/include/support/android/locale_bionic.h index 50fcf5c36..d638757fd 100644 --- a/include/support/android/locale_bionic.h +++ b/include/support/android/locale_bionic.h @@ -40,18 +40,18 @@ extern "C" { extern "C" { #endif -inline _LIBCPP_INLINE_VISIBILITY float strtof_l(const char* __nptr, char** __endptr, - locale_t) { +inline _LIBCPP_ALWAYS_INLINE float strtof_l(const char* __nptr, char** __endptr, + locale_t) { return ::strtof(__nptr, __endptr); } -inline _LIBCPP_INLINE_VISIBILITY double strtod_l(const char* __nptr, - char** __endptr, locale_t) { +inline _LIBCPP_ALWAYS_INLINE double strtod_l(const char* __nptr, + char** __endptr, locale_t) { return ::strtod(__nptr, __endptr); } -inline _LIBCPP_INLINE_VISIBILITY long strtol_l(const char* __nptr, char** __endptr, - int __base, locale_t) { +inline _LIBCPP_ALWAYS_INLINE long strtol_l(const char* __nptr, char** __endptr, + int __base, locale_t) { return ::strtol(__nptr, __endptr, __base); } diff --git a/include/support/xlocale/__posix_l_fallback.h b/include/support/xlocale/__posix_l_fallback.h index b9a0939f8..c893a6731 100644 --- a/include/support/xlocale/__posix_l_fallback.h +++ b/include/support/xlocale/__posix_l_fallback.h @@ -20,141 +20,141 @@ extern "C" { #endif -inline _LIBCPP_INLINE_VISIBILITY int isalnum_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int isalnum_l(int c, locale_t) { return ::isalnum(c); } -inline _LIBCPP_INLINE_VISIBILITY int isalpha_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int isalpha_l(int c, locale_t) { return ::isalpha(c); } -inline _LIBCPP_INLINE_VISIBILITY int isblank_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int isblank_l(int c, locale_t) { return ::isblank(c); } -inline _LIBCPP_INLINE_VISIBILITY int iscntrl_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iscntrl_l(int c, locale_t) { return ::iscntrl(c); } -inline _LIBCPP_INLINE_VISIBILITY int isdigit_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int isdigit_l(int c, locale_t) { return ::isdigit(c); } -inline _LIBCPP_INLINE_VISIBILITY int isgraph_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int isgraph_l(int c, locale_t) { return ::isgraph(c); } -inline _LIBCPP_INLINE_VISIBILITY int islower_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int islower_l(int c, locale_t) { return ::islower(c); } -inline _LIBCPP_INLINE_VISIBILITY int isprint_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int isprint_l(int c, locale_t) { return ::isprint(c); } -inline _LIBCPP_INLINE_VISIBILITY int ispunct_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int ispunct_l(int c, locale_t) { return ::ispunct(c); } -inline _LIBCPP_INLINE_VISIBILITY int isspace_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int isspace_l(int c, locale_t) { return ::isspace(c); } -inline _LIBCPP_INLINE_VISIBILITY int isupper_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int isupper_l(int c, locale_t) { return ::isupper(c); } -inline _LIBCPP_INLINE_VISIBILITY int isxdigit_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int isxdigit_l(int c, locale_t) { return ::isxdigit(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswalnum_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswalnum_l(wint_t c, locale_t) { return ::iswalnum(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswalpha_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswalpha_l(wint_t c, locale_t) { return ::iswalpha(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswblank_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswblank_l(wint_t c, locale_t) { return ::iswblank(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswcntrl_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswcntrl_l(wint_t c, locale_t) { return ::iswcntrl(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswdigit_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswdigit_l(wint_t c, locale_t) { return ::iswdigit(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswgraph_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswgraph_l(wint_t c, locale_t) { return ::iswgraph(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswlower_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswlower_l(wint_t c, locale_t) { return ::iswlower(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswprint_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswprint_l(wint_t c, locale_t) { return ::iswprint(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswpunct_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswpunct_l(wint_t c, locale_t) { return ::iswpunct(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswspace_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswspace_l(wint_t c, locale_t) { return ::iswspace(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswupper_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswupper_l(wint_t c, locale_t) { return ::iswupper(c); } -inline _LIBCPP_INLINE_VISIBILITY int iswxdigit_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int iswxdigit_l(wint_t c, locale_t) { return ::iswxdigit(c); } -inline _LIBCPP_INLINE_VISIBILITY int toupper_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int toupper_l(int c, locale_t) { return ::toupper(c); } -inline _LIBCPP_INLINE_VISIBILITY int tolower_l(int c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int tolower_l(int c, locale_t) { return ::tolower(c); } -inline _LIBCPP_INLINE_VISIBILITY wint_t towupper_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE wint_t towupper_l(wint_t c, locale_t) { return ::towupper(c); } -inline _LIBCPP_INLINE_VISIBILITY wint_t towlower_l(wint_t c, locale_t) { +inline _LIBCPP_ALWAYS_INLINE wint_t towlower_l(wint_t c, locale_t) { return ::towlower(c); } -inline _LIBCPP_INLINE_VISIBILITY int strcoll_l(const char *s1, const char *s2, - locale_t) { +inline _LIBCPP_ALWAYS_INLINE int strcoll_l(const char *s1, const char *s2, + locale_t) { return ::strcoll(s1, s2); } -inline _LIBCPP_INLINE_VISIBILITY size_t strxfrm_l(char *dest, const char *src, - size_t n, locale_t) { +inline _LIBCPP_ALWAYS_INLINE size_t strxfrm_l(char *dest, const char *src, + size_t n, locale_t) { return ::strxfrm(dest, src, n); } -inline _LIBCPP_INLINE_VISIBILITY size_t strftime_l(char *s, size_t max, - const char *format, - const struct tm *tm, locale_t) { +inline _LIBCPP_ALWAYS_INLINE size_t strftime_l(char *s, size_t max, + const char *format, + const struct tm *tm, locale_t) { return ::strftime(s, max, format, tm); } -inline _LIBCPP_INLINE_VISIBILITY int wcscoll_l(const wchar_t *ws1, - const wchar_t *ws2, locale_t) { +inline _LIBCPP_ALWAYS_INLINE int wcscoll_l(const wchar_t *ws1, + const wchar_t *ws2, locale_t) { return ::wcscoll(ws1, ws2); } -inline _LIBCPP_INLINE_VISIBILITY size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, - size_t n, locale_t) { +inline _LIBCPP_ALWAYS_INLINE size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, + size_t n, locale_t) { return ::wcsxfrm(dest, src, n); } diff --git a/include/support/xlocale/__strtonum_fallback.h b/include/support/xlocale/__strtonum_fallback.h index 50b4db354..4ae3918b3 100644 --- a/include/support/xlocale/__strtonum_fallback.h +++ b/include/support/xlocale/__strtonum_fallback.h @@ -20,43 +20,43 @@ extern "C" { #endif -inline _LIBCPP_INLINE_VISIBILITY float strtof_l(const char *nptr, - char **endptr, locale_t) { +inline _LIBCPP_ALWAYS_INLINE float strtof_l(const char *nptr, + char **endptr, locale_t) { return ::strtof(nptr, endptr); } -inline _LIBCPP_INLINE_VISIBILITY double strtod_l(const char *nptr, - char **endptr, locale_t) { +inline _LIBCPP_ALWAYS_INLINE double strtod_l(const char *nptr, + char **endptr, locale_t) { return ::strtod(nptr, endptr); } -inline _LIBCPP_INLINE_VISIBILITY long double strtold_l(const char *nptr, - char **endptr, locale_t) { +inline _LIBCPP_ALWAYS_INLINE long double strtold_l(const char *nptr, + char **endptr, locale_t) { return ::strtold(nptr, endptr); } -inline _LIBCPP_INLINE_VISIBILITY long long +inline _LIBCPP_ALWAYS_INLINE long long strtoll_l(const char *nptr, char **endptr, int base, locale_t) { return ::strtoll(nptr, endptr, base); } -inline _LIBCPP_INLINE_VISIBILITY unsigned long long +inline _LIBCPP_ALWAYS_INLINE unsigned long long strtoull_l(const char *nptr, char **endptr, int base, locale_t) { return ::strtoull(nptr, endptr, base); } -inline _LIBCPP_INLINE_VISIBILITY long long +inline _LIBCPP_ALWAYS_INLINE long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, int base, locale_t) { return ::wcstoll(nptr, endptr, base); } -inline _LIBCPP_INLINE_VISIBILITY unsigned long long +inline _LIBCPP_ALWAYS_INLINE unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr, int base, locale_t) { return ::wcstoull(nptr, endptr, base); } -inline _LIBCPP_INLINE_VISIBILITY long double wcstold_l(const wchar_t *nptr, - wchar_t **endptr, locale_t) { +inline _LIBCPP_ALWAYS_INLINE long double wcstold_l(const wchar_t *nptr, + wchar_t **endptr, locale_t) { return ::wcstold(nptr, endptr); } diff --git a/include/system_error b/include/system_error index 917c71029..f5d8d1145 100644 --- a/include/system_error +++ b/include/system_error @@ -203,7 +203,7 @@ public: defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) error_category() _NOEXCEPT; #else - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR_AFTER_CXX11 error_category() _NOEXCEPT _LIBCPP_DEFAULT #endif private: @@ -217,13 +217,13 @@ public: virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT; virtual string message(int __ev) const = 0; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE bool operator==(const error_category& __rhs) const _NOEXCEPT {return this == &__rhs;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE bool operator!=(const error_category& __rhs) const _NOEXCEPT {return !(*this == __rhs);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE bool operator< (const error_category& __rhs) const _NOEXCEPT {return this < &__rhs;} friend class _LIBCPP_HIDDEN __do_message; @@ -244,21 +244,21 @@ class _LIBCPP_TYPE_VIS error_condition int __val_; const error_category* __cat_; public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE error_condition() _NOEXCEPT : __val_(0), __cat_(&generic_category()) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE error_condition(int __val, const error_category& __cat) _NOEXCEPT : __val_(__val), __cat_(&__cat) {} template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE error_condition(_Ep __e, typename enable_if::value>::type* = 0 ) _NOEXCEPT {*this = make_error_condition(__e);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void assign(int __val, const error_category& __cat) _NOEXCEPT { __val_ = __val; @@ -266,7 +266,7 @@ public: } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE typename enable_if < is_error_condition_enum<_Ep>::value, @@ -275,21 +275,21 @@ public: operator=(_Ep __e) _NOEXCEPT {*this = make_error_condition(__e); return *this;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void clear() _NOEXCEPT { __val_ = 0; __cat_ = &generic_category(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int value() const _NOEXCEPT {return __val_;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const error_category& category() const _NOEXCEPT {return *__cat_;} string message() const; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __val_ != 0;} }; @@ -316,21 +316,21 @@ class _LIBCPP_TYPE_VIS error_code int __val_; const error_category* __cat_; public: - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE error_code() _NOEXCEPT : __val_(0), __cat_(&system_category()) {} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE error_code(int __val, const error_category& __cat) _NOEXCEPT : __val_(__val), __cat_(&__cat) {} template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE error_code(_Ep __e, typename enable_if::value>::type* = 0 ) _NOEXCEPT {*this = make_error_code(__e);} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void assign(int __val, const error_category& __cat) _NOEXCEPT { __val_ = __val; @@ -338,7 +338,7 @@ public: } template - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE typename enable_if < is_error_code_enum<_Ep>::value, @@ -347,26 +347,26 @@ public: operator=(_Ep __e) _NOEXCEPT {*this = make_error_code(__e); return *this;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE void clear() _NOEXCEPT { __val_ = 0; __cat_ = &system_category(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE int value() const _NOEXCEPT {return __val_;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const error_category& category() const _NOEXCEPT {return *__cat_;} - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE error_condition default_error_condition() const _NOEXCEPT {return __cat_->default_error_condition(__val_);} string message() const; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __val_ != 0;} }; @@ -472,7 +472,7 @@ public: system_error(int __ev, const error_category& __ecat); ~system_error() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_ALWAYS_INLINE const error_code& code() const _NOEXCEPT {return __ec_;} private: diff --git a/include/typeinfo b/include/typeinfo index f32ea6e76..74d94e9e3 100644 --- a/include/typeinfo +++ b/include/typeinfo @@ -226,7 +226,7 @@ public: #endif // defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) _LIBCPP_BEGIN_NAMESPACE_STD -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE void __throw_bad_cast() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/vector b/include/vector index 0f5006f37..74c423ef2 100644 --- a/include/vector +++ b/include/vector @@ -295,7 +295,7 @@ template class __vector_base_common { protected: - _LIBCPP_INLINE_VISIBILITY __vector_base_common() {} + _LIBCPP_ALWAYS_INLINE __vector_base_common() {} _LIBCPP_NORETURN void __throw_length_error() const; _LIBCPP_NORETURN void __throw_out_of_range() const; }; diff --git a/src/support/win32/thread_win32.cpp b/src/support/win32/thread_win32.cpp index 471049429..3f479443e 100644 --- a/src/support/win32/thread_win32.cpp +++ b/src/support/win32/thread_win32.cpp @@ -138,7 +138,7 @@ int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) } // Execute Once -static inline _LIBCPP_INLINE_VISIBILITY BOOL CALLBACK +static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK __libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter, PVOID *__context) { @@ -178,7 +178,7 @@ struct __libcpp_beginthreadex_thunk_data void *__arg; }; -static inline _LIBCPP_INLINE_VISIBILITY unsigned WINAPI +static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI __libcpp_beginthreadex_thunk(void *__raw_data) { auto *__data = -- GitLab From 57288eb81d63ce87ca2bb39184a994f01b86a652 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Sun, 8 Jul 2018 00:06:27 +0000 Subject: [PATCH 015/495] type_traits: aligned_union is NOT the same as __uncvref [NFC] git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336502 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/type_traits | 50 ++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/include/type_traits b/include/type_traits index 7234b981f..30bfb161c 100644 --- a/include/type_traits +++ b/include/type_traits @@ -21,7 +21,7 @@ namespace std template struct integral_constant; typedef integral_constant true_type; // C++11 typedef integral_constant false_type; // C++11 - + template // C++14 using bool_constant = integral_constant; // C++14 typedef bool_constant true_type; // C++14 @@ -172,7 +172,7 @@ namespace std using add_volatile_t = typename add_volatile::type; // C++14 template using add_cv_t = typename add_cv::type; // C++14 - + // reference modifications: template using remove_reference_t = typename remove_reference::type; // C++14 @@ -180,13 +180,13 @@ namespace std using add_lvalue_reference_t = typename add_lvalue_reference::type; // C++14 template using add_rvalue_reference_t = typename add_rvalue_reference::type; // C++14 - + // sign modifications: template using make_signed_t = typename make_signed::type; // C++14 template using make_unsigned_t = typename make_unsigned::type; // C++14 - + // array modifications: template using remove_extent_t = typename remove_extent::type; // C++14 @@ -223,7 +223,7 @@ namespace std template using void_t = void; // C++17 - + // See C++14 20.10.4.1, primary type categories template inline constexpr bool is_void_v = is_void::value; // C++17 @@ -386,13 +386,13 @@ namespace std // [meta.logical], logical operator traits: template struct conjunction; // C++17 - template + template inline constexpr bool conjunction_v = conjunction::value; // C++17 template struct disjunction; // C++17 template inline constexpr bool disjunction_v = disjunction::value; // C++17 template struct negation; // C++17 - template + template inline constexpr bool negation_v = negation::value; // C++17 } @@ -595,7 +595,7 @@ template struct __and_<_B0, _B1> : conditional<_B0::value, _B1, _B0>::type {}; template -struct __and_<_B0, _B1, _B2, _Bn...> +struct __and_<_B0, _B1, _B2, _Bn...> : conditional<_B0::value, __and_<_B1, _B2, _Bn...>, _B0>::type {}; // __or_ @@ -608,11 +608,11 @@ template struct __or_<_B0, _B1> : conditional<_B0::value, _B0, _B1>::type {}; template -struct __or_<_B0, _B1, _B2, _Bn...> +struct __or_<_B0, _B1, _B2, _Bn...> : conditional<_B0::value, _B0, __or_<_B1, _B2, _Bn...> >::type {}; // __not_ -template +template struct __not_ : conditional<_Tp::value, false_type, true_type>::type {}; #endif // !defined(_LIBCPP_CXX03_LANG) @@ -903,7 +903,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_function_v // template struct __libcpp_is_member_function_pointer : public false_type {}; // template struct __libcpp_is_member_function_pointer<_Tp _Up::*> : public is_function<_Tp> {}; -// +// template struct __member_pointer_traits_imp @@ -1184,7 +1184,7 @@ struct __is_same_uncvref : is_same::type, typename __uncvref<_Up>::type> {}; #if _LIBCPP_STD_VER > 17 -// aligned_union - same as __uncvref +// remove_cvref - same as __uncvref template struct remove_cvref : public __uncvref<_Tp> {}; @@ -1211,12 +1211,12 @@ template using remove_pointer_t = typename remove_pointer<_Tp>::type // add_pointer -template ::value || +template ::value || is_same::type, void>::value> struct __add_pointer_impl {typedef typename remove_reference<_Tp>::type* type;}; -template struct __add_pointer_impl<_Tp, false> +template struct __add_pointer_impl<_Tp, false> {typedef _Tp type;}; template struct _LIBCPP_TEMPLATE_VIS add_pointer @@ -1630,7 +1630,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool has_virtual_destructor_v #if _LIBCPP_STD_VER > 14 && defined(_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS) template struct _LIBCPP_TEMPLATE_VIS has_unique_object_representations - : public integral_constant>)> {}; #if !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) @@ -2241,7 +2241,7 @@ struct __is_destructor_wellformed { template static __two __test (...); - + static const bool value = sizeof(__test<_Tp>(12)) == sizeof(char); }; @@ -2249,8 +2249,8 @@ template struct __destructible_imp; template -struct __destructible_imp<_Tp, false> - : public _VSTD::integral_constant + : public _VSTD::integral_constant::type>::value> {}; template @@ -3401,7 +3401,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_default_constructible_v template struct _LIBCPP_TEMPLATE_VIS is_copy_constructible - : public is_constructible<_Tp, + : public is_constructible<_Tp, typename add_lvalue_reference::type>::type> {}; #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) @@ -4109,7 +4109,7 @@ template struct _LIBCPP_TEMPLATE_VIS is_literal_type is_reference::type>::value> #endif {}; - + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_literal_type_v @@ -4125,7 +4125,7 @@ template struct _LIBCPP_TEMPLATE_VIS is_standard_layout : integral_constant::type>::value> #endif {}; - + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_standard_layout_v @@ -4143,7 +4143,7 @@ template struct _LIBCPP_TEMPLATE_VIS is_trivially_copyable : integral_constant::type>::value> #endif {}; - + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_trivially_copyable_v @@ -4830,7 +4830,7 @@ template constexpr typename enable_if, byte>::type & operator<<=(byte& __lhs, _Integer __shift) noexcept { return __lhs = __lhs << __shift; } - + template constexpr typename enable_if, byte>::type operator<< (byte __lhs, _Integer __shift) noexcept @@ -4845,7 +4845,7 @@ template constexpr typename enable_if, byte>::type operator>> (byte __lhs, _Integer __shift) noexcept { return static_cast(static_cast(static_cast(__lhs) >> __shift)); } - + template constexpr typename enable_if, _Integer>::type to_integer(byte __b) noexcept { return static_cast<_Integer>(__b); } -- GitLab From 8df0521f96b6fe40b51e6fd9f1dc1d8c5b6f2aab Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 9 Jul 2018 23:45:09 +0000 Subject: [PATCH 016/495] [test] two small cleanups: * Remove unused type from is_assignable.pass.cpp * Don't specialize `common_type<::X>` in common_type.pass.cpp, which violates the requirements of [meta.trans.other]/5 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336618 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../meta/meta.trans/meta.trans.other/common_type.pass.cpp | 5 ++--- .../meta/meta.unary/meta.unary.prop/is_assignable.pass.cpp | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp index 85b147266..dbbbe159f 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp @@ -11,8 +11,9 @@ // common_type -#include +#include #include +#include #include "test_macros.h" @@ -45,7 +46,6 @@ namespace std template <> struct common_type< ::S, long> {}; template <> struct common_type > {}; - template <> struct common_type< ::X > {}; template <> struct common_type< ::X, ::X > {}; } @@ -97,7 +97,6 @@ void test_bullet_two() { static_assert(std::is_same, int volatile*>::value, ""); static_assert(std::is_same, void(*)()>::value, ""); - static_assert(no_common_type >::value, ""); static_assert(no_common_type >::value, ""); } diff --git a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_assignable.pass.cpp b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_assignable.pass.cpp index 8d63a2349..4808a4dc9 100644 --- a/test/std/utilities/meta/meta.unary/meta.unary.prop/is_assignable.pass.cpp +++ b/test/std/utilities/meta/meta.unary/meta.unary.prop/is_assignable.pass.cpp @@ -59,8 +59,6 @@ struct E template struct X { T t; }; -struct Incomplete; - int main() { test_is_assignable (); -- GitLab From ffc31db6619b60f9232d9e485b68e53a68423777 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Tue, 10 Jul 2018 04:02:00 +0000 Subject: [PATCH 017/495] Update google-benchark to trunk git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336635 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/google-benchmark/AUTHORS | 4 + utils/google-benchmark/CMakeLists.txt | 55 +++- utils/google-benchmark/CONTRIBUTORS | 4 + utils/google-benchmark/README.md | 39 ++- .../cmake/AddCXXCompilerFlag.cmake | 10 + .../cmake/CXXFeatureCheck.cmake | 36 +-- .../cmake/GetGitVersion.cmake | 3 + .../google-benchmark/cmake/HandleGTest.cmake | 78 +++-- utils/google-benchmark/cmake/split_list.cmake | 3 + utils/google-benchmark/docs/AssemblyTests.md | 147 +++++++++ .../include/benchmark/benchmark.h | 286 +++++++++++------- utils/google-benchmark/releasing.md | 16 + utils/google-benchmark/src/CMakeLists.txt | 25 +- utils/google-benchmark/src/benchmark.cc | 206 ++++--------- .../src/benchmark_api_internal.h | 2 +- utils/google-benchmark/src/benchmark_main.cc | 17 ++ .../src/benchmark_register.cc | 83 +++-- .../google-benchmark/src/benchmark_register.h | 33 ++ utils/google-benchmark/src/check.h | 5 +- .../google-benchmark/src/commandlineflags.cc | 2 +- utils/google-benchmark/src/complexity.cc | 25 +- utils/google-benchmark/src/counter.cc | 25 +- utils/google-benchmark/src/counter.h | 8 +- utils/google-benchmark/src/csv_reporter.cc | 20 +- utils/google-benchmark/src/cycleclock.h | 7 +- utils/google-benchmark/src/internal_macros.h | 20 +- utils/google-benchmark/src/json_reporter.cc | 46 ++- utils/google-benchmark/src/log.h | 3 +- utils/google-benchmark/src/re.h | 44 ++- utils/google-benchmark/src/reporter.cc | 6 + utils/google-benchmark/src/statistics.cc | 46 +-- utils/google-benchmark/src/string_util.cc | 95 +++++- utils/google-benchmark/src/string_util.h | 28 +- utils/google-benchmark/src/sysinfo.cc | 86 +++++- utils/google-benchmark/src/thread_manager.h | 66 ++++ utils/google-benchmark/src/thread_timer.h | 69 +++++ utils/google-benchmark/src/timers.cc | 11 +- utils/google-benchmark/test/BUILD | 65 ++++ utils/google-benchmark/test/CMakeLists.txt | 50 ++- utils/google-benchmark/test/basic_test.cc | 20 +- .../google-benchmark/test/benchmark_gtest.cc | 33 ++ utils/google-benchmark/test/benchmark_test.cc | 29 +- .../test/clobber_memory_assembly_test.cc | 64 ++++ .../google-benchmark/test/complexity_test.cc | 17 +- .../test/donotoptimize_assembly_test.cc | 163 ++++++++++ .../test/donotoptimize_test.cc | 6 +- utils/google-benchmark/test/link_main_test.cc | 8 + utils/google-benchmark/test/map_test.cc | 12 +- .../test/multiple_ranges_test.cc | 33 +- utils/google-benchmark/test/output_test.h | 29 +- .../test/output_test_helper.cc | 96 +++--- .../test/register_benchmark_test.cc | 2 + .../test/reporter_output_test.cc | 31 +- .../test/skip_with_error_test.cc | 17 +- .../test/state_assembly_test.cc | 68 +++++ .../google-benchmark/test/statistics_gtest.cc | 28 ++ .../google-benchmark/test/statistics_test.cc | 61 ---- .../test/string_util_gtest.cc | 146 +++++++++ .../test/templated_fixture_test.cc | 6 +- .../test/user_counters_tabular_test.cc | 66 ++-- .../test/user_counters_test.cc | 209 +++++++++++-- utils/google-benchmark/tools/compare.py | 67 +++- .../tools/gbench/Inputs/test3_run0.json | 39 +++ .../tools/gbench/Inputs/test3_run1.json | 39 +++ utils/google-benchmark/tools/gbench/report.py | 186 ++++++++++-- utils/google-benchmark/tools/strip_asm.py | 151 +++++++++ 66 files changed, 2671 insertions(+), 729 deletions(-) create mode 100644 utils/google-benchmark/cmake/split_list.cmake create mode 100644 utils/google-benchmark/docs/AssemblyTests.md create mode 100644 utils/google-benchmark/releasing.md create mode 100644 utils/google-benchmark/src/benchmark_main.cc create mode 100644 utils/google-benchmark/src/benchmark_register.h create mode 100644 utils/google-benchmark/src/thread_manager.h create mode 100644 utils/google-benchmark/src/thread_timer.h create mode 100644 utils/google-benchmark/test/BUILD create mode 100644 utils/google-benchmark/test/benchmark_gtest.cc create mode 100644 utils/google-benchmark/test/clobber_memory_assembly_test.cc create mode 100644 utils/google-benchmark/test/donotoptimize_assembly_test.cc create mode 100644 utils/google-benchmark/test/link_main_test.cc create mode 100644 utils/google-benchmark/test/state_assembly_test.cc create mode 100644 utils/google-benchmark/test/statistics_gtest.cc delete mode 100644 utils/google-benchmark/test/statistics_test.cc create mode 100644 utils/google-benchmark/test/string_util_gtest.cc create mode 100644 utils/google-benchmark/tools/gbench/Inputs/test3_run0.json create mode 100644 utils/google-benchmark/tools/gbench/Inputs/test3_run1.json create mode 100755 utils/google-benchmark/tools/strip_asm.py diff --git a/utils/google-benchmark/AUTHORS b/utils/google-benchmark/AUTHORS index 4e4c4ed47..daea1f66f 100644 --- a/utils/google-benchmark/AUTHORS +++ b/utils/google-benchmark/AUTHORS @@ -13,11 +13,13 @@ Arne Beer Carto Christopher Seymour David Coeurjolly +Deniz Evrenci Dirac Research Dominik Czarnota Eric Fiselier Eugene Zhuk Evgeny Safronov +Federico Ficarelli Felix Homann Google Inc. International Business Machines Corporation @@ -31,6 +33,7 @@ Kishan Kumar Lei Xu Matt Clarkson Maxim Vafin +MongoDB Inc. Nick Hutchinson Oleksandr Sochka Paul Redmond @@ -38,6 +41,7 @@ Radoslav Yovchev Roman Lebedev Shuo Chen Steinar H. Gunderson +Stripe, Inc. Yixuan Qiu Yusuke Suzuki Zbigniew Skowron diff --git a/utils/google-benchmark/CMakeLists.txt b/utils/google-benchmark/CMakeLists.txt index aa0826760..8ddacabb6 100644 --- a/utils/google-benchmark/CMakeLists.txt +++ b/utils/google-benchmark/CMakeLists.txt @@ -27,10 +27,48 @@ option(BENCHMARK_DOWNLOAD_DEPENDENCIES "Allow the downloading and in-tree buildi # in cases where it is not possible to build or find a valid version of gtest. option(BENCHMARK_ENABLE_GTEST_TESTS "Enable building the unit tests which depend on gtest" ON) +set(ENABLE_ASSEMBLY_TESTS_DEFAULT OFF) +function(should_enable_assembly_tests) + if(CMAKE_BUILD_TYPE) + string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER) + if (${CMAKE_BUILD_TYPE_LOWER} MATCHES "coverage") + # FIXME: The --coverage flag needs to be removed when building assembly + # tests for this to work. + return() + endif() + endif() + if (MSVC) + return() + elseif(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + return() + elseif(NOT CMAKE_SIZEOF_VOID_P EQUAL 8) + # FIXME: Make these work on 32 bit builds + return() + elseif(BENCHMARK_BUILD_32_BITS) + # FIXME: Make these work on 32 bit builds + return() + endif() + find_program(LLVM_FILECHECK_EXE FileCheck) + if (LLVM_FILECHECK_EXE) + set(LLVM_FILECHECK_EXE "${LLVM_FILECHECK_EXE}" CACHE PATH "llvm filecheck" FORCE) + message(STATUS "LLVM FileCheck Found: ${LLVM_FILECHECK_EXE}") + else() + message(STATUS "Failed to find LLVM FileCheck") + return() + endif() + set(ENABLE_ASSEMBLY_TESTS_DEFAULT ON PARENT_SCOPE) +endfunction() +should_enable_assembly_tests() + +# This option disables the building and running of the assembly verification tests +option(BENCHMARK_ENABLE_ASSEMBLY_TESTS "Enable building and running the assembly tests" + ${ENABLE_ASSEMBLY_TESTS_DEFAULT}) + # Make sure we can import out CMake functions list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + # Read the git tags to determine the project version include(GetGitVersion) get_git_version(GIT_VERSION) @@ -92,7 +130,6 @@ else() # Turn compiler warnings up to 11 add_cxx_compiler_flag(-Wall) - add_cxx_compiler_flag(-Wextra) add_cxx_compiler_flag(-Wshadow) add_cxx_compiler_flag(-Werror RELEASE) @@ -101,8 +138,20 @@ else() add_cxx_compiler_flag(-pedantic) add_cxx_compiler_flag(-pedantic-errors) add_cxx_compiler_flag(-Wshorten-64-to-32) - add_cxx_compiler_flag(-Wfloat-equal) add_cxx_compiler_flag(-fstrict-aliasing) + # Disable warnings regarding deprecated parts of the library while building + # and testing those parts of the library. + add_cxx_compiler_flag(-Wno-deprecated-declarations) + if (CMAKE_CXX_COMPILER_ID STREQUAL "Intel") + # Intel silently ignores '-Wno-deprecated-declarations', + # warning no. 1786 must be explicitly disabled. + # See #631 for rationale. + add_cxx_compiler_flag(-wd1786) + endif() + # Disable deprecation warnings for release builds (when -Werror is enabled). + add_cxx_compiler_flag(-Wno-deprecated RELEASE) + add_cxx_compiler_flag(-Wno-deprecated RELWITHDEBINFO) + add_cxx_compiler_flag(-Wno-deprecated MINSIZEREL) if (NOT BENCHMARK_ENABLE_EXCEPTIONS) add_cxx_compiler_flag(-fno-exceptions) endif() @@ -178,7 +227,7 @@ if (BENCHMARK_USE_LIBCXX) # linker flags appear before all linker inputs and -lc++ must appear after. list(APPEND BENCHMARK_CXX_LIBRARIES c++) else() - message(FATAL "-DBENCHMARK_USE_LIBCXX:BOOL=ON is not supported for compiler") + message(FATAL_ERROR "-DBENCHMARK_USE_LIBCXX:BOOL=ON is not supported for compiler") endif() endif(BENCHMARK_USE_LIBCXX) diff --git a/utils/google-benchmark/CONTRIBUTORS b/utils/google-benchmark/CONTRIBUTORS index c59134b9b..2ff2f2a8f 100644 --- a/utils/google-benchmark/CONTRIBUTORS +++ b/utils/google-benchmark/CONTRIBUTORS @@ -28,16 +28,19 @@ Billy Robert O'Neal III Chris Kennelly Christopher Seymour David Coeurjolly +Deniz Evrenci Dominic Hamon Dominik Czarnota Eric Fiselier Eugene Zhuk Evgeny Safronov +Federico Ficarelli Felix Homann Ismael Jimenez Martinez Jern-Kuan Leong JianXiong Zhou Joao Paulo Magalhaes +John Millikin Jussi Knuuttila Kai Wolf Kishan Kumar @@ -53,6 +56,7 @@ Pierre Phaneuf Radoslav Yovchev Raul Marin Ray Glover +Robert Guo Roman Lebedev Shuo Chen Tobias Ulvgård diff --git a/utils/google-benchmark/README.md b/utils/google-benchmark/README.md index 6bd81e701..80e69f6e1 100644 --- a/utils/google-benchmark/README.md +++ b/utils/google-benchmark/README.md @@ -14,6 +14,8 @@ IRC channel: https://freenode.net #googlebenchmark [Additional Tooling Documentation](docs/tools.md) +[Assembly Testing Documentation](docs/AssemblyTests.md) + ## Building @@ -21,7 +23,7 @@ The basic steps for configuring and building the library look like this: ```bash $ git clone https://github.com/google/benchmark.git -# Benchmark requires GTest as a dependency. Add the source tree as a subdirectory. +# Benchmark requires Google Test as a dependency. Add the source tree as a subdirectory. $ git clone https://github.com/google/googletest.git benchmark/googletest $ mkdir build && cd build $ cmake -G [options] ../benchmark @@ -29,15 +31,13 @@ $ cmake -G [options] ../benchmark $ make ``` -Note that Google Benchmark requires GTest to build and run the tests. This -dependency can be provided three ways: +Note that Google Benchmark requires Google Test to build and run the tests. This +dependency can be provided two ways: -* Checkout the GTest sources into `benchmark/googletest`. +* Checkout the Google Test sources into `benchmark/googletest` as above. * Otherwise, if `-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON` is specified during configuration, the library will automatically download and build any required dependencies. -* Otherwise, if nothing is done, CMake will use `find_package(GTest REQUIRED)` - to resolve the required GTest dependency. If you do not wish to build and run the tests, add `-DBENCHMARK_ENABLE_GTEST_TESTS=OFF` to `CMAKE_ARGS`. @@ -59,6 +59,7 @@ 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 mkdir build cd build cmake .. -DCMAKE_BUILD_TYPE=RELEASE @@ -71,7 +72,7 @@ We need to install the library globally now sudo make install ``` -Now you have google/benchmark installed in your machine +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 @@ -86,6 +87,11 @@ 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 + ## Example usage ### Basic usage @@ -112,7 +118,10 @@ BENCHMARK(BM_StringCopy); BENCHMARK_MAIN(); ``` -Don't forget to inform your linker to add benchmark library e.g. through `-lbenchmark` compilation flag. +Don't forget to inform your linker to add benchmark library e.g. through +`-lbenchmark` compilation flag. Alternatively, you may leave out the +`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. @@ -821,7 +830,7 @@ BM_SetInsert/1024/10 33157 33648 21431 1.13369M The JSON format outputs human readable json split into two top level attributes. The `context` attribute contains information about the run in general, including information about the CPU and the date. -The `benchmarks` attribute contains a list of ever benchmark run. Example json +The `benchmarks` attribute contains a list of every benchmark run. Example json output looks like: ```json { @@ -893,8 +902,11 @@ If you are using gcc, you might need to set `GCC_AR` and `GCC_RANLIB` cmake cach If you are using clang, you may need to set `LLVMAR_EXECUTABLE`, `LLVMNM_EXECUTABLE` and `LLVMRANLIB_EXECUTABLE` cmake cache variables. ## Linking against the library -When using gcc, it is necessary to link against pthread to avoid runtime exceptions. -This is due to how gcc implements std::thread. + +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. ## Compiler Support @@ -928,8 +940,11 @@ sudo cpupower frequency-set --governor powersave # Known Issues -### Windows +### 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/utils/google-benchmark/cmake/AddCXXCompilerFlag.cmake b/utils/google-benchmark/cmake/AddCXXCompilerFlag.cmake index 17d5f3dcc..d0d209981 100644 --- a/utils/google-benchmark/cmake/AddCXXCompilerFlag.cmake +++ b/utils/google-benchmark/cmake/AddCXXCompilerFlag.cmake @@ -62,3 +62,13 @@ function(add_required_cxx_compiler_flag FLAG) message(FATAL_ERROR "Required flag '${FLAG}' is not supported by the compiler") endif() endfunction() + +function(check_cxx_warning_flag FLAG) + mangle_compiler_flag("${FLAG}" MANGLED_FLAG) + set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + # Add -Werror to ensure the compiler generates an error if the warning flag + # doesn't exist. + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror ${FLAG}") + check_cxx_compiler_flag("${FLAG}" ${MANGLED_FLAG}) + set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}") +endfunction() diff --git a/utils/google-benchmark/cmake/CXXFeatureCheck.cmake b/utils/google-benchmark/cmake/CXXFeatureCheck.cmake index b2a821715..c4c4d660f 100644 --- a/utils/google-benchmark/cmake/CXXFeatureCheck.cmake +++ b/utils/google-benchmark/cmake/CXXFeatureCheck.cmake @@ -27,25 +27,27 @@ function(cxx_feature_check FILE) return() endif() - message("-- Performing Test ${FEATURE}") - if(CMAKE_CROSSCOMPILING) - try_compile(COMPILE_${FEATURE} - ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp - CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS} - LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES}) - if(COMPILE_${FEATURE}) - message(WARNING - "If you see build failures due to cross compilation, try setting HAVE_${VAR} to 0") - set(RUN_${FEATURE} 0) + if (NOT DEFINED COMPILE_${FEATURE}) + message("-- Performing Test ${FEATURE}") + if(CMAKE_CROSSCOMPILING) + try_compile(COMPILE_${FEATURE} + ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${FILE}.cpp + CMAKE_FLAGS ${BENCHMARK_CXX_LINKER_FLAGS} + LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES}) + if(COMPILE_${FEATURE}) + message(WARNING + "If you see build failures due to cross compilation, try setting HAVE_${VAR} to 0") + set(RUN_${FEATURE} 0) + else() + set(RUN_${FEATURE} 1) + endif() else() - set(RUN_${FEATURE} 1) + message("-- 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} + LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES}) endif() - else() - message("-- 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} - LINK_LIBRARIES ${BENCHMARK_CXX_LIBRARIES}) endif() if(RUN_${FEATURE} EQUAL 0) diff --git a/utils/google-benchmark/cmake/GetGitVersion.cmake b/utils/google-benchmark/cmake/GetGitVersion.cmake index 8dd948004..88cebe3a1 100644 --- a/utils/google-benchmark/cmake/GetGitVersion.cmake +++ b/utils/google-benchmark/cmake/GetGitVersion.cmake @@ -21,6 +21,7 @@ set(__get_git_version INCLUDED) function(get_git_version var) if(GIT_EXECUTABLE) execute_process(COMMAND ${GIT_EXECUTABLE} describe --match "v[0-9]*.[0-9]*.[0-9]*" --abbrev=8 + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} RESULT_VARIABLE status OUTPUT_VARIABLE GIT_VERSION ERROR_QUIET) @@ -33,9 +34,11 @@ function(get_git_version var) # Work out if the repository is dirty execute_process(COMMAND ${GIT_EXECUTABLE} update-index -q --refresh + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_QUIET ERROR_QUIET) execute_process(COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD -- + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE GIT_DIFF_INDEX ERROR_QUIET) string(COMPARE NOTEQUAL "${GIT_DIFF_INDEX}" "" GIT_DIRTY) diff --git a/utils/google-benchmark/cmake/HandleGTest.cmake b/utils/google-benchmark/cmake/HandleGTest.cmake index 77ffc4c51..7ce1a633d 100644 --- a/utils/google-benchmark/cmake/HandleGTest.cmake +++ b/utils/google-benchmark/cmake/HandleGTest.cmake @@ -1,7 +1,5 @@ -macro(split_list listname) - string(REPLACE ";" " " ${listname} "${${listname}}") -endmacro() +include(split_list) macro(build_external_gtest) include(ExternalProject) @@ -23,9 +21,22 @@ macro(build_external_gtest) if ("${GTEST_BUILD_TYPE}" STREQUAL "COVERAGE") set(GTEST_BUILD_TYPE "DEBUG") endif() + # FIXME: Since 10/Feb/2017 the googletest trunk has had a bug where + # -Werror=unused-function fires during the build on OS X. This is a temporary + # workaround to keep our travis bots from failing. It should be removed + # once gtest is fixed. + if (NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + list(APPEND GTEST_FLAGS "-Wno-unused-function") + endif() split_list(GTEST_FLAGS) + set(EXCLUDE_FROM_ALL_OPT "") + set(EXCLUDE_FROM_ALL_VALUE "") + if (${CMAKE_VERSION} VERSION_GREATER "3.0.99") + set(EXCLUDE_FROM_ALL_OPT "EXCLUDE_FROM_ALL") + set(EXCLUDE_FROM_ALL_VALUE "ON") + endif() ExternalProject_Add(googletest - EXCLUDE_FROM_ALL ON + ${EXCLUDE_FROM_ALL_OPT} ${EXCLUDE_FROM_ALL_VALUE} GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG master PREFIX "${CMAKE_BINARY_DIR}/googletest" @@ -35,45 +46,68 @@ macro(build_external_gtest) -DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER} -DCMAKE_INSTALL_PREFIX:PATH= + -DCMAKE_INSTALL_LIBDIR:PATH=/lib -DCMAKE_CXX_FLAGS:STRING=${GTEST_FLAGS} -Dgtest_force_shared_crt:BOOL=ON ) ExternalProject_Get_Property(googletest install_dir) - - add_library(gtest UNKNOWN IMPORTED) - add_library(gtest_main UNKNOWN IMPORTED) + set(GTEST_INCLUDE_DIRS ${install_dir}/include) + file(MAKE_DIRECTORY ${GTEST_INCLUDE_DIRS}) set(LIB_SUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}") set(LIB_PREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}") - if("${GTEST_BUILD_TYPE}" STREQUAL "DEBUG") set(LIB_SUFFIX "d${CMAKE_STATIC_LIBRARY_SUFFIX}") endif() - file(MAKE_DIRECTORY ${install_dir}/include) - set_target_properties(gtest PROPERTIES - IMPORTED_LOCATION ${install_dir}/lib/${LIB_PREFIX}gtest${LIB_SUFFIX} - INTERFACE_INCLUDE_DIRECTORIES ${install_dir}/include - ) - set_target_properties(gtest_main PROPERTIES - IMPORTED_LOCATION ${install_dir}/lib/${LIB_PREFIX}gtest_main${LIB_SUFFIX} - INTERFACE_INCLUDE_DIRECTORIES ${install_dir}/include - ) - add_dependencies(gtest googletest) - add_dependencies(gtest_main googletest) - set(GTEST_BOTH_LIBRARIES gtest gtest_main) - #set(GTEST_INCLUDE_DIRS ${install_dir}/include) + + # Use gmock_main instead of gtest_main because it initializes gtest as well. + # Note: The libraries are listed in reverse order of their dependancies. + foreach(LIB gtest gmock gmock_main) + add_library(${LIB} UNKNOWN IMPORTED) + set_target_properties(${LIB} PROPERTIES + IMPORTED_LOCATION ${install_dir}/lib/${LIB_PREFIX}${LIB}${LIB_SUFFIX} + INTERFACE_INCLUDE_DIRECTORIES ${GTEST_INCLUDE_DIRS} + INTERFACE_LINK_LIBRARIES "${GTEST_BOTH_LIBRARIES}" + ) + add_dependencies(${LIB} googletest) + list(APPEND GTEST_BOTH_LIBRARIES ${LIB}) + endforeach() endmacro(build_external_gtest) if (BENCHMARK_ENABLE_GTEST_TESTS) if (IS_DIRECTORY ${CMAKE_SOURCE_DIR}/googletest) + set(GTEST_ROOT "${CMAKE_SOURCE_DIR}/googletest") set(INSTALL_GTEST OFF CACHE INTERNAL "") set(INSTALL_GMOCK OFF CACHE INTERNAL "") add_subdirectory(${CMAKE_SOURCE_DIR}/googletest) - set(GTEST_BOTH_LIBRARIES gtest gtest_main) + 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 + # have to add the paths ourselves. + set(HFILE g${HEADER}/g${HEADER}.h) + set(HPATH ${GTEST_ROOT}/google${HEADER}/include) + find_path(HEADER_PATH_${HEADER} ${HFILE} + NO_DEFAULT_PATHS + HINTS ${HPATH} + ) + if (NOT HEADER_PATH_${HEADER}) + message(FATAL_ERROR "Failed to find header ${HFILE} in ${HPATH}") + endif() + list(APPEND GTEST_INCLUDE_DIRS ${HEADER_PATH_${HEADER}}) + endforeach() elseif(BENCHMARK_DOWNLOAD_DEPENDENCIES) build_external_gtest() else() find_package(GTest REQUIRED) + find_path(GMOCK_INCLUDE_DIRS gmock/gmock.h + HINTS ${GTEST_INCLUDE_DIRS}) + if (NOT GMOCK_INCLUDE_DIRS) + message(FATAL_ERROR "Failed to find header gmock/gmock.h with hint ${GTEST_INCLUDE_DIRS}") + endif() + set(GTEST_INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS}) + # FIXME: We don't currently require the gmock library to build the tests, + # and it's likely we won't find it, so we don't try. As long as we've + # found the gmock/gmock.h header and gtest_main that should be good enough. endif() endif() diff --git a/utils/google-benchmark/cmake/split_list.cmake b/utils/google-benchmark/cmake/split_list.cmake new file mode 100644 index 000000000..67aed3fdc --- /dev/null +++ b/utils/google-benchmark/cmake/split_list.cmake @@ -0,0 +1,3 @@ +macro(split_list listname) + string(REPLACE ";" " " ${listname} "${${listname}}") +endmacro() diff --git a/utils/google-benchmark/docs/AssemblyTests.md b/utils/google-benchmark/docs/AssemblyTests.md new file mode 100644 index 000000000..1fbdc269b --- /dev/null +++ b/utils/google-benchmark/docs/AssemblyTests.md @@ -0,0 +1,147 @@ +# Assembly Tests + +The Benchmark library provides a number of functions whose primary +purpose in to affect assembly generation, including `DoNotOptimize` +and `ClobberMemory`. In addition there are other functions, +such as `KeepRunning`, for which generating good assembly is paramount. + +For these functions it's important to have tests that verify the +correctness and quality of the implementation. This requires testing +the code generated by the compiler. + +This document describes how the Benchmark library tests compiler output, +as well as how to properly write new tests. + + +## Anatomy of a Test + +Writing a test has two steps: + +* Write the code you want to generate assembly for. +* Add `// CHECK` lines to match against the verified assembly. + +Example: +```c++ + +// CHECK-LABEL: test_add: +extern "C" int test_add() { + extern int ExternInt; + return ExternInt + 1; + + // CHECK: movl ExternInt(%rip), %eax + // CHECK: addl %eax + // CHECK: ret +} + +``` + +#### LLVM Filecheck + +[LLVM's Filecheck](https://llvm.org/docs/CommandGuide/FileCheck.html) +is used to test the generated assembly against the `// CHECK` lines +specified in the tests source file. Please see the documentation +linked above for information on how to write `CHECK` directives. + +#### Tips and Tricks: + +* Tests should match the minimal amount of output required to establish +correctness. `CHECK` directives don't have to match on the exact next line +after the previous match, so tests should omit checks for unimportant +bits of assembly. ([`CHECK-NEXT`](https://llvm.org/docs/CommandGuide/FileCheck.html#the-check-next-directive) +can be used to ensure a match occurs exactly after the previous match). + +* The tests are compiled with `-O3 -g0`. So we're only testing the +optimized output. + +* The assembly output is further cleaned up using `tools/strip_asm.py`. +This removes comments, assembler directives, and unused labels before +the test is run. + +* The generated and stripped assembly file for a test is output under +`/test/.s` + +* Filecheck supports using [`CHECK` prefixes](https://llvm.org/docs/CommandGuide/FileCheck.html#cmdoption-check-prefixes) +to specify lines that should only match in certain situations. +The Benchmark tests use `CHECK-CLANG` and `CHECK-GNU` for lines that +are only expected to match Clang or GCC's output respectively. Normal +`CHECK` lines match against all compilers. (Note: `CHECK-NOT` and +`CHECK-LABEL` are NOT prefixes. They are versions of non-prefixed +`CHECK` lines) + +* Use `extern "C"` to disable name mangling for specific functions. This +makes them easier to name in the `CHECK` lines. + + +## Problems Writing Portable Tests + +Writing tests which check the code generated by a compiler are +inherently non-portable. Different compilers and even different compiler +versions may generate entirely different code. The Benchmark tests +must tolerate this. + +LLVM Filecheck provides a number of mechanisms to help write +"more portable" tests; including [matching using regular expressions](https://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-pattern-matching-syntax), +allowing the creation of [named variables](https://llvm.org/docs/CommandGuide/FileCheck.html#filecheck-variables) +for later matching, and [checking non-sequential matches](https://llvm.org/docs/CommandGuide/FileCheck.html#the-check-dag-directive). + +#### Capturing Variables + +For example, say GCC stores a variable in a register but Clang stores +it in memory. To write a test that tolerates both cases we "capture" +the destination of the store, and then use the captured expression +to write the remainder of the test. + +```c++ +// CHECK-LABEL: test_div_no_op_into_shr: +extern "C" void test_div_no_op_into_shr(int value) { + int divisor = 2; + benchmark::DoNotOptimize(divisor); // hide the value from the optimizer + return value / divisor; + + // CHECK: movl $2, [[DEST:.*]] + // CHECK: idivl [[DEST]] + // CHECK: ret +} +``` + +#### Using Regular Expressions to Match Differing Output + +Often tests require testing assembly lines which may subtly differ +between compilers or compiler versions. A common example of this +is matching stack frame addresses. In this case regular expressions +can be used to match the differing bits of output. For example: + +```c++ +int ExternInt; +struct Point { int x, y, z; }; + +// CHECK-LABEL: test_store_point: +extern "C" void test_store_point() { + Point p{ExternInt, ExternInt, ExternInt}; + benchmark::DoNotOptimize(p); + + // CHECK: movl ExternInt(%rip), %eax + // CHECK: movl %eax, -{{[0-9]+}}(%rsp) + // CHECK: movl %eax, -{{[0-9]+}}(%rsp) + // CHECK: movl %eax, -{{[0-9]+}}(%rsp) + // CHECK: ret +} +``` + +## Current Requirements and Limitations + +The tests require Filecheck to be installed along the `PATH` of the +build machine. Otherwise the tests will be disabled. + +Additionally, as mentioned in the previous section, codegen tests are +inherently non-portable. Currently the tests are limited to: + +* x86_64 targets. +* Compiled with GCC or Clang + +Further work could be done, at least on a limited basis, to extend the +tests to other architectures and compilers (using `CHECK` prefixes). + +Furthermore, the tests fail for builds which specify additional flags +that modify code generation, including `--coverage` or `-fsanitize=`. + diff --git a/utils/google-benchmark/include/benchmark/benchmark.h b/utils/google-benchmark/include/benchmark/benchmark.h index 340cbc1ec..193fffc4b 100644 --- a/utils/google-benchmark/include/benchmark/benchmark.h +++ b/utils/google-benchmark/include/benchmark/benchmark.h @@ -164,7 +164,6 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #ifndef BENCHMARK_BENCHMARK_H_ #define BENCHMARK_BENCHMARK_H_ - // The _MSVC_LANG check should detect Visual Studio 2015 Update 3 and newer. #if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L) #define BENCHMARK_HAS_CXX11 @@ -172,22 +171,23 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #include +#include #include #include #include -#include -#include #include #include +#include +#include #if defined(BENCHMARK_HAS_CXX11) -#include #include +#include #include #endif #if defined(_MSC_VER) -#include // for _ReadWriteBarrier +#include // for _ReadWriteBarrier #endif #ifndef BENCHMARK_HAS_CXX11 @@ -226,13 +226,15 @@ BENCHMARK(BM_test)->Unit(benchmark::kMillisecond); #define BENCHMARK_INTERNAL_TOSTRING2(x) #x #define BENCHMARK_INTERNAL_TOSTRING(x) BENCHMARK_INTERNAL_TOSTRING2(x) -#if defined(__GNUC__) +#if defined(__GNUC__) || defined(__clang__) #define BENCHMARK_BUILTIN_EXPECT(x, y) __builtin_expect(x, y) #define BENCHMARK_DEPRECATED_MSG(msg) __attribute__((deprecated(msg))) #else #define BENCHMARK_BUILTIN_EXPECT(x, y) x #define BENCHMARK_DEPRECATED_MSG(msg) -#define BENCHMARK_WARNING_MSG(msg) __pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING(__LINE__) ") : warning note: " msg)) +#define BENCHMARK_WARNING_MSG(msg) \ + __pragma(message(__FILE__ "(" BENCHMARK_INTERNAL_TOSTRING( \ + __LINE__) ") : warning note: " msg)) #endif #if defined(__GNUC__) && !defined(__clang__) @@ -289,13 +291,11 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams(); } // namespace internal - #if (!defined(__GNUC__) && !defined(__clang__)) || defined(__pnacl__) || \ - defined(EMSCRIPTN) -# define BENCHMARK_HAS_NO_INLINE_ASSEMBLY + defined(__EMSCRIPTEN__) +#define BENCHMARK_HAS_NO_INLINE_ASSEMBLY #endif - // The DoNotOptimize(...) function can be used to prevent a value or // expression from being optimized away by the compiler. This function is // intended to add little to no overhead. @@ -303,14 +303,18 @@ BENCHMARK_UNUSED static int stream_init_anchor = InitializeStreams(); #ifndef BENCHMARK_HAS_NO_INLINE_ASSEMBLY template inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { - // Clang doesn't like the 'X' constraint on `value` and certain GCC versions - // don't like the 'g' constraint. Attempt to placate them both. + asm volatile("" : : "r,m"(value) : "memory"); +} + +template +inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp& value) { #if defined(__clang__) - asm volatile("" : : "g"(value) : "memory"); + asm volatile("" : "+r,m"(value) : : "memory"); #else - asm volatile("" : : "i,r,m"(value) : "memory"); + asm volatile("" : "+m,r"(value) : : "memory"); #endif } + // Force the compiler to flush pending writes to global memory. Acts as an // effective read/write barrier inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { @@ -323,9 +327,7 @@ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { _ReadWriteBarrier(); } -inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { - _ReadWriteBarrier(); -} +inline BENCHMARK_ALWAYS_INLINE void ClobberMemory() { _ReadWriteBarrier(); } #else template inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { @@ -334,39 +336,54 @@ inline BENCHMARK_ALWAYS_INLINE void DoNotOptimize(Tp const& value) { // FIXME Add ClobberMemory() for non-gnu and non-msvc compilers #endif - - // This class is used for user-defined counters. class Counter { -public: - + public: enum Flags { - kDefaults = 0, + kDefaults = 0, // Mark the counter as a rate. It will be presented divided // by the duration of the benchmark. - kIsRate = 1, + kIsRate = 1U << 0U, // Mark the counter as a thread-average quantity. It will be // presented divided by the number of threads. - kAvgThreads = 2, + kAvgThreads = 1U << 1U, // Mark the counter as a thread-average rate. See above. - kAvgThreadsRate = kIsRate|kAvgThreads + kAvgThreadsRate = kIsRate | kAvgThreads, + // Mark the counter as a constant value, valid/same for *every* iteration. + // When reporting, it will be *multiplied* by the iteration count. + kIsIterationInvariant = 1U << 2U, + // Mark the counter as a constant rate. + // When reporting, it will be *multiplied* by the iteration count + // and then divided by the duration of the benchmark. + kIsIterationInvariantRate = kIsRate | kIsIterationInvariant, + // Mark the counter as a iteration-average quantity. + // It will be presented divided by the number of iterations. + kAvgIterations = 1U << 3U, + // Mark the counter as a iteration-average rate. See above. + kAvgIterationsRate = kIsRate | kAvgIterations }; double value; - Flags flags; + Flags flags; BENCHMARK_ALWAYS_INLINE Counter(double v = 0., Flags f = kDefaults) : value(v), flags(f) {} - BENCHMARK_ALWAYS_INLINE operator double const& () const { return value; } - BENCHMARK_ALWAYS_INLINE operator double & () { return value; } - + BENCHMARK_ALWAYS_INLINE operator double const&() const { return value; } + BENCHMARK_ALWAYS_INLINE operator double&() { return value; } }; +// A helper for user code to create unforeseen combinations of Flags, without +// having to do this cast manually each time, or providing this operator. +Counter::Flags inline operator|(const Counter::Flags& LHS, + const Counter::Flags& RHS) { + return static_cast(static_cast(LHS) | + static_cast(RHS)); +} + // This is the container for the user-defined counters. typedef std::map UserCounters; - // TimeUnit is passed to a benchmark in order to specify the order of magnitude // for the measured time. enum TimeUnit { kNanosecond, kMicrosecond, kMillisecond }; @@ -379,7 +396,7 @@ enum BigO { oNone, o1, oN, oNSquared, oNCubed, oLogN, oNLogN, oAuto, oLambda }; // BigOFunc is passed to a benchmark in order to specify the asymptotic // computational complexity for the benchmark. -typedef double(BigOFunc)(int); +typedef double(BigOFunc)(int64_t); // StatisticsFunc is passed to a benchmark in order to compute some descriptive // statistics over all the measurements of some type @@ -390,7 +407,7 @@ struct Statistics { StatisticsFunc* compute_; Statistics(std::string name, StatisticsFunc* compute) - : name_(name), compute_(compute) {} + : name_(name), compute_(compute) {} }; namespace internal { @@ -399,14 +416,12 @@ class ThreadManager; enum ReportMode #if defined(BENCHMARK_HAS_CXX11) - : unsigned + : unsigned #else #endif - { - RM_Unspecified, // The mode has not been manually specified +{ RM_Unspecified, // The mode has not been manually specified RM_Default, // The mode is user-specified as default. - RM_ReportAggregatesOnly -}; + RM_ReportAggregatesOnly }; } // namespace internal // State is passed to a running Benchmark and contains state for the @@ -429,16 +444,19 @@ class State { // Returns true if the benchmark should continue through another iteration. // NOTE: A benchmark may not return from the test until KeepRunning() has // returned false. - bool KeepRunning() { - if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) { - StartKeepRunning(); - } - bool const res = (--total_iterations_ != 0); - if (BENCHMARK_BUILTIN_EXPECT(!res, false)) { - FinishKeepRunning(); - } - return res; - } + bool KeepRunning(); + + // Returns true iff the benchmark should run n more iterations. + // REQUIRES: 'n' > 0. + // NOTE: A benchmark must not return from the test until KeepRunningBatch() + // has returned false. + // NOTE: KeepRunningBatch() may overshoot by up to 'n' iterations. + // + // Intended usage: + // while (state.KeepRunningBatch(1000)) { + // // process 1000 elements + // } + bool KeepRunningBatch(size_t n); // REQUIRES: timer is running and 'SkipWithError(...)' has not been called // by the current thread. @@ -505,10 +523,10 @@ class State { // // REQUIRES: a benchmark has exited its benchmarking loop. BENCHMARK_ALWAYS_INLINE - void SetBytesProcessed(size_t bytes) { bytes_processed_ = bytes; } + void SetBytesProcessed(int64_t bytes) { bytes_processed_ = bytes; } BENCHMARK_ALWAYS_INLINE - size_t bytes_processed() const { return bytes_processed_; } + int64_t bytes_processed() const { return bytes_processed_; } // If this routine is called with complexity_n > 0 and complexity report is // requested for the @@ -516,10 +534,10 @@ class State { // and complexity_n will // represent the length of N. BENCHMARK_ALWAYS_INLINE - void SetComplexityN(int complexity_n) { complexity_n_ = complexity_n; } + void SetComplexityN(int64_t complexity_n) { complexity_n_ = complexity_n; } BENCHMARK_ALWAYS_INLINE - int complexity_length_n() { return complexity_n_; } + int64_t complexity_length_n() { return complexity_n_; } // If this routine is called with items > 0, then an items/s // label is printed on the benchmark report line for the currently @@ -528,10 +546,10 @@ class State { // // REQUIRES: a benchmark has exited its benchmarking loop. BENCHMARK_ALWAYS_INLINE - void SetItemsProcessed(size_t items) { items_processed_ = items; } + void SetItemsProcessed(int64_t items) { items_processed_ = items; } BENCHMARK_ALWAYS_INLINE - size_t items_processed() const { return items_processed_; } + int64_t items_processed() const { return items_processed_; } // If this routine is called, the specified label is printed at the // end of the benchmark report line for the currently executing @@ -539,7 +557,7 @@ class State { // static void BM_Compress(benchmark::State& state) { // ... // double compress = input_size / output_size; - // state.SetLabel(StringPrintf("compress:%.1f%%", 100.0*compression)); + // state.SetLabel(StrFormat("compress:%.1f%%", 100.0*compression)); // } // Produces output that looks like: // BM_Compress 50 50 14115038 compress:27.3% @@ -553,33 +571,51 @@ class State { // Range arguments for this run. CHECKs if the argument has been set. BENCHMARK_ALWAYS_INLINE - int range(std::size_t pos = 0) const { + int64_t range(std::size_t pos = 0) const { assert(range_.size() > pos); return range_[pos]; } BENCHMARK_DEPRECATED_MSG("use 'range(0)' instead") - int range_x() const { return range(0); } + int64_t range_x() const { return range(0); } BENCHMARK_DEPRECATED_MSG("use 'range(1)' instead") - int range_y() const { return range(1); } + int64_t range_y() const { return range(1); } BENCHMARK_ALWAYS_INLINE - size_t iterations() const { return (max_iterations - total_iterations_) + 1; } + size_t iterations() const { + if (BENCHMARK_BUILTIN_EXPECT(!started_, false)) { + return 0; + } + return max_iterations - total_iterations_ + batch_leftover_; + } + + private + : // items we expect on the first cache line (ie 64 bytes of the struct) + // When total_iterations_ is 0, KeepRunning() and friends will return false. + // May be larger than max_iterations. + size_t total_iterations_; + + // When using KeepRunningBatch(), batch_leftover_ holds the number of + // iterations beyond max_iters that were run. Used to track + // completed_iterations_ accurately. + size_t batch_leftover_; + + public: + const size_t max_iterations; private: bool started_; bool finished_; - size_t total_iterations_; - - std::vector range_; + bool error_occurred_; - size_t bytes_processed_; - size_t items_processed_; + private: // items we don't need on the first cache line + std::vector range_; - int complexity_n_; + int64_t bytes_processed_; + int64_t items_processed_; - bool error_occurred_; + int64_t complexity_n_; public: // Container for user-defined counters. @@ -588,27 +624,66 @@ class State { const int thread_index; // Number of threads concurrently executing the benchmark. const int threads; - const size_t max_iterations; // TODO(EricWF) make me private - State(size_t max_iters, const std::vector& ranges, int thread_i, + State(size_t max_iters, const std::vector& 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. + bool KeepRunningInternal(size_t n, bool is_batch); void FinishKeepRunning(); internal::ThreadTimer* timer_; internal::ThreadManager* manager_; BENCHMARK_DISALLOW_COPY_AND_ASSIGN(State); }; +inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunning() { + return KeepRunningInternal(1, /*is_batch=*/false); +} + +inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningBatch(size_t n) { + return KeepRunningInternal(n, /*is_batch=*/true); +} + +inline BENCHMARK_ALWAYS_INLINE bool State::KeepRunningInternal(size_t n, + bool is_batch) { + // total_iterations_ is set to 0 by the constructor, and always set to a + // nonzero value by StartKepRunning(). + assert(n > 0); + // n must be 1 unless is_batch is true. + assert(is_batch || n == 1); + if (BENCHMARK_BUILTIN_EXPECT(total_iterations_ >= n, true)) { + total_iterations_ -= n; + return true; + } + if (!started_) { + StartKeepRunning(); + if (!error_occurred_ && total_iterations_ >= n) { + total_iterations_ -= n; + return true; + } + } + // For non-batch runs, total_iterations_ must be 0 by now. + if (is_batch && total_iterations_ != 0) { + batch_leftover_ = n - total_iterations_; + total_iterations_ = 0; + return true; + } + FinishKeepRunning(); + return false; +} + struct State::StateIterator { struct BENCHMARK_UNUSED Value {}; typedef std::forward_iterator_tag iterator_category; typedef Value value_type; typedef Value reference; typedef Value pointer; + typedef std::ptrdiff_t difference_type; private: friend class State; @@ -670,7 +745,7 @@ class Benchmark { // Run this benchmark once with "x" as the extra argument passed // to the function. // REQUIRES: The function passed to the constructor must accept an arg1. - Benchmark* Arg(int x); + Benchmark* Arg(int64_t x); // Run this benchmark with the given time unit for the generated output report Benchmark* Unit(TimeUnit unit); @@ -678,23 +753,23 @@ class Benchmark { // Run this benchmark once for a number of values picked from the // range [start..limit]. (start and limit are always picked.) // REQUIRES: The function passed to the constructor must accept an arg1. - Benchmark* Range(int start, int limit); + Benchmark* Range(int64_t start, int64_t limit); // Run this benchmark once for all values in the range [start..limit] with // specific step // REQUIRES: The function passed to the constructor must accept an arg1. - Benchmark* DenseRange(int start, int limit, int step = 1); + Benchmark* DenseRange(int64_t start, int64_t limit, int step = 1); // Run this benchmark once with "args" as the extra arguments passed // to the function. // REQUIRES: The function passed to the constructor must accept arg1, arg2 ... - Benchmark* Args(const std::vector& args); + Benchmark* Args(const std::vector& args); // Equivalent to Args({x, y}) // NOTE: This is a legacy C++03 interface provided for compatibility only. // New code should use 'Args'. - Benchmark* ArgPair(int x, int y) { - std::vector args; + Benchmark* ArgPair(int64_t x, int64_t y) { + std::vector args; args.push_back(x); args.push_back(y); return Args(args); @@ -703,7 +778,7 @@ class Benchmark { // Run this benchmark once for a number of values picked from the // ranges [start..limit]. (starts and limits are always picked.) // REQUIRES: The function passed to the constructor must accept arg1, arg2 ... - Benchmark* Ranges(const std::vector >& ranges); + Benchmark* Ranges(const std::vector >& ranges); // Equivalent to ArgNames({name}) Benchmark* ArgName(const std::string& name); @@ -715,8 +790,8 @@ class Benchmark { // Equivalent to Ranges({{lo1, hi1}, {lo2, hi2}}). // NOTE: This is a legacy C++03 interface provided for compatibility only. // New code should use 'Ranges'. - Benchmark* RangePair(int lo1, int hi1, int lo2, int hi2) { - std::vector > ranges; + Benchmark* RangePair(int64_t lo1, int64_t hi1, int64_t lo2, int64_t hi2) { + std::vector > ranges; ranges.push_back(std::make_pair(lo1, hi1)); ranges.push_back(std::make_pair(lo2, hi2)); return Ranges(ranges); @@ -823,15 +898,13 @@ class Benchmark { int ArgsCnt() const; - static void AddRange(std::vector* dst, int lo, int hi, int mult); - private: friend class BenchmarkFamilies; std::string name_; ReportMode report_mode_; - std::vector arg_names_; // Args for all benchmark runs - std::vector > args_; // Args for all benchmark runs + std::vector arg_names_; // Args for all benchmark runs + std::vector > args_; // Args for all benchmark runs TimeUnit time_unit_; int range_multiplier_; double min_time_; @@ -1055,7 +1128,7 @@ class Fixture : public internal::Benchmark { class BaseClass##_##Method##_Benchmark : public BaseClass { \ public: \ BaseClass##_##Method##_Benchmark() : BaseClass() { \ - this->SetName(#BaseClass"<" #a ">/" #Method); \ + this->SetName(#BaseClass "<" #a ">/" #Method); \ } \ \ protected: \ @@ -1066,7 +1139,7 @@ class Fixture : public internal::Benchmark { class BaseClass##_##Method##_Benchmark : public BaseClass { \ public: \ BaseClass##_##Method##_Benchmark() : BaseClass() { \ - this->SetName(#BaseClass"<" #a "," #b ">/" #Method); \ + this->SetName(#BaseClass "<" #a "," #b ">/" #Method); \ } \ \ protected: \ @@ -1078,14 +1151,15 @@ class Fixture : public internal::Benchmark { class BaseClass##_##Method##_Benchmark : public BaseClass<__VA_ARGS__> { \ public: \ BaseClass##_##Method##_Benchmark() : BaseClass<__VA_ARGS__>() { \ - this->SetName(#BaseClass"<" #__VA_ARGS__ ">/" #Method); \ + this->SetName(#BaseClass "<" #__VA_ARGS__ ">/" #Method); \ } \ \ protected: \ virtual void BenchmarkCase(::benchmark::State&); \ }; #else -#define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(n, a) BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(n, a) +#define BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(n, a) \ + BENCHMARK_TEMPLATE1_PRIVATE_DECLARE_F(n, a) #endif #define BENCHMARK_DEFINE_F(BaseClass, Method) \ @@ -1105,7 +1179,8 @@ class Fixture : public internal::Benchmark { BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \ void BaseClass##_##Method##_Benchmark::BenchmarkCase #else -#define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, a) BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a) +#define BENCHMARK_TEMPLATE_DEFINE_F(BaseClass, Method, a) \ + BENCHMARK_TEMPLATE1_DEFINE_F(BaseClass, Method, a) #endif #define BENCHMARK_REGISTER_F(BaseClass, Method) \ @@ -1132,24 +1207,24 @@ class Fixture : public internal::Benchmark { void BaseClass##_##Method##_Benchmark::BenchmarkCase #ifdef BENCHMARK_HAS_CXX11 -#define BENCHMARK_TEMPLATE_F(BaseClass, Method, ...) \ +#define BENCHMARK_TEMPLATE_F(BaseClass, Method, ...) \ BENCHMARK_TEMPLATE_PRIVATE_DECLARE_F(BaseClass, Method, __VA_ARGS__) \ - BENCHMARK_REGISTER_F(BaseClass, Method); \ + BENCHMARK_REGISTER_F(BaseClass, Method); \ void BaseClass##_##Method##_Benchmark::BenchmarkCase #else -#define BENCHMARK_TEMPLATE_F(BaseClass, Method, a) BENCHMARK_TEMPLATE1_F(BaseClass, Method, a) +#define BENCHMARK_TEMPLATE_F(BaseClass, Method, a) \ + BENCHMARK_TEMPLATE1_F(BaseClass, Method, a) #endif // Helper macro to create a main routine in a test that runs the benchmarks -#define BENCHMARK_MAIN() \ - int main(int argc, char** argv) { \ - ::benchmark::Initialize(&argc, argv); \ +#define BENCHMARK_MAIN() \ + int main(int argc, char** argv) { \ + ::benchmark::Initialize(&argc, argv); \ if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; \ - ::benchmark::RunSpecifiedBenchmarks(); \ - } \ + ::benchmark::RunSpecifiedBenchmarks(); \ + } \ int main(int, char**) - // ------------------------------------------------------ // Benchmark Reporters @@ -1186,7 +1261,7 @@ class BenchmarkReporter { CPUInfo const& cpu_info; // The number of chars in the longest benchmark name. size_t name_field_width; - + static const char* executable_name; Context(); }; @@ -1239,7 +1314,7 @@ class BenchmarkReporter { // Keep track of arguments to compute asymptotic complexity BigO complexity; BigOFunc* complexity_lambda; - int complexity_n; + int64_t complexity_n; // what statistics to compute from the measurements const std::vector* statistics; @@ -1309,17 +1384,19 @@ class BenchmarkReporter { // Simple reporter that outputs benchmark data to the console. This is the // default reporter used by RunSpecifiedBenchmarks(). class ConsoleReporter : public BenchmarkReporter { -public: + public: enum OutputOptions { OO_None = 0, OO_Color = 1, OO_Tabular = 2, - OO_ColorTabular = OO_Color|OO_Tabular, + OO_ColorTabular = OO_Color | OO_Tabular, OO_Defaults = OO_ColorTabular }; explicit ConsoleReporter(OutputOptions opts_ = OO_Defaults) - : output_options_(opts_), name_field_width_(0), - prev_counters_(), printed_header_(false) {} + : output_options_(opts_), + name_field_width_(0), + prev_counters_(), + printed_header_(false) {} virtual bool ReportContext(const Context& context); virtual void ReportRuns(const std::vector& reports); @@ -1347,7 +1424,8 @@ class JSONReporter : public BenchmarkReporter { bool first_report_; }; -class CSVReporter : public BenchmarkReporter { +class BENCHMARK_DEPRECATED_MSG("The CSV Reporter will be removed in a future release") + CSVReporter : public BenchmarkReporter { public: CSVReporter() : printed_header_(false) {} virtual bool ReportContext(const Context& context); @@ -1357,7 +1435,7 @@ class CSVReporter : public BenchmarkReporter { void PrintRunData(const Run& report); bool printed_header_; - std::set< std::string > user_counter_names_; + std::set user_counter_names_; }; inline const char* GetTimeUnitString(TimeUnit unit) { @@ -1384,6 +1462,6 @@ inline double GetTimeUnitMultiplier(TimeUnit unit) { } } -} // namespace benchmark +} // namespace benchmark #endif // BENCHMARK_BENCHMARK_H_ diff --git a/utils/google-benchmark/releasing.md b/utils/google-benchmark/releasing.md new file mode 100644 index 000000000..f0cd7010e --- /dev/null +++ b/utils/google-benchmark/releasing.md @@ -0,0 +1,16 @@ +# How to release + +* Make sure you're on master and synced to HEAD +* Ensure the project builds and tests run (sanity check only, obviously) + * `parallel -j0 exec ::: test/*_test` can help ensure everything at least + passes +* Prepare release notes + * `git log $(git describe --abbrev=0 --tags)..HEAD` gives you the list of + commits between the last annotated tag and HEAD + * Pick the most interesting. +* Create a release through github's interface + * Note this will create a lightweight tag. + * Update this to an annotated tag: + * `git pull --tags` + * `git tag -a -f ` + * `git push --force origin` diff --git a/utils/google-benchmark/src/CMakeLists.txt b/utils/google-benchmark/src/CMakeLists.txt index e22620a72..977474f43 100644 --- a/utils/google-benchmark/src/CMakeLists.txt +++ b/utils/google-benchmark/src/CMakeLists.txt @@ -11,6 +11,10 @@ file(GLOB *.cc ${PROJECT_SOURCE_DIR}/include/benchmark/*.h ${CMAKE_CURRENT_SOURCE_DIR}/*.h) +file(GLOB BENCHMARK_MAIN "benchmark_main.cc") +foreach(item ${BENCHMARK_MAIN}) + list(REMOVE_ITEM SOURCE_FILES "${item}") +endforeach() add_library(benchmark ${SOURCE_FILES}) set_target_properties(benchmark PROPERTIES @@ -34,6 +38,23 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_link_libraries(benchmark Shlwapi) endif() +# We need extra libraries on Solaris +if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + target_link_libraries(benchmark kstat) +endif() + +# Benchmark main library +add_library(benchmark_main "benchmark_main.cc") +set_target_properties(benchmark_main PROPERTIES + OUTPUT_NAME "benchmark_main" + VERSION ${GENERIC_LIB_VERSION} + SOVERSION ${GENERIC_LIB_SOVERSION} +) +target_include_directories(benchmark PUBLIC + $ + ) +target_link_libraries(benchmark_main benchmark) + set(include_install_dir "include") set(lib_install_dir "lib/") set(bin_install_dir "bin/") @@ -51,7 +72,7 @@ set(namespace "${PROJECT_NAME}::") include(CMakePackageConfigHelpers) write_basic_package_version_file( - "${version_config}" VERSION ${GIT_VERSION} COMPATIBILITY SameMajorVersion + "${version_config}" VERSION ${GENERIC_LIB_VERSION} COMPATIBILITY SameMajorVersion ) configure_file("${PROJECT_SOURCE_DIR}/cmake/Config.cmake.in" "${project_config}" @ONLY) @@ -60,7 +81,7 @@ configure_file("${PROJECT_SOURCE_DIR}/cmake/benchmark.pc.in" "${pkg_config}" @ON if (BENCHMARK_ENABLE_INSTALL) # Install target (will install the library to specified CMAKE_INSTALL_PREFIX variable) install( - TARGETS benchmark + TARGETS benchmark benchmark_main EXPORT ${targets_export_name} ARCHIVE DESTINATION ${lib_install_dir} LIBRARY DESTINATION ${lib_install_dir} diff --git a/utils/google-benchmark/src/benchmark.cc b/utils/google-benchmark/src/benchmark.cc index 1a7d21828..b14bc6291 100644 --- a/utils/google-benchmark/src/benchmark.cc +++ b/utils/google-benchmark/src/benchmark.cc @@ -17,7 +17,9 @@ #include "internal_macros.h" #ifndef BENCHMARK_OS_WINDOWS +#ifndef BENCHMARK_OS_FUCHSIA #include +#endif #include #include #endif @@ -27,10 +29,10 @@ #include #include #include -#include #include #include #include +#include #include #include "check.h" @@ -44,7 +46,8 @@ #include "re.h" #include "statistics.h" #include "string_util.h" -#include "timers.h" +#include "thread_manager.h" +#include "thread_timer.h" DEFINE_bool(benchmark_list_tests, false, "Print a list of benchmarks. This option overrides all other " @@ -82,7 +85,7 @@ DEFINE_string(benchmark_out_format, "json", "The format to use for file output. Valid values are " "'console', 'json', or 'csv'."); -DEFINE_string(benchmark_out, "", "The file to write additonal output to"); +DEFINE_string(benchmark_out, "", "The file to write additional output to"); DEFINE_string(benchmark_color, "auto", "Whether to use colors in the output. Valid values: " @@ -108,119 +111,11 @@ namespace internal { void UseCharPointer(char const volatile*) {} -class ThreadManager { - public: - ThreadManager(int num_threads) - : alive_threads_(num_threads), start_stop_barrier_(num_threads) {} - - Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) { - return benchmark_mutex_; - } - - bool StartStopBarrier() EXCLUDES(end_cond_mutex_) { - return start_stop_barrier_.wait(); - } - - void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) { - start_stop_barrier_.removeThread(); - if (--alive_threads_ == 0) { - MutexLock lock(end_cond_mutex_); - end_condition_.notify_all(); - } - } - - void WaitForAllThreads() EXCLUDES(end_cond_mutex_) { - MutexLock lock(end_cond_mutex_); - end_condition_.wait(lock.native_handle(), - [this]() { return alive_threads_ == 0; }); - } - - public: - struct Result { - 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; - int complexity_n = 0; - std::string report_label_; - std::string error_message_; - bool has_error_ = false; - UserCounters counters; - }; - GUARDED_BY(GetBenchmarkMutex()) Result results; - - private: - mutable Mutex benchmark_mutex_; - std::atomic alive_threads_; - Barrier start_stop_barrier_; - Mutex end_cond_mutex_; - Condition end_condition_; -}; - -// Timer management class -class ThreadTimer { - public: - ThreadTimer() = default; - - // Called by each thread - void StartTimer() { - running_ = true; - start_real_time_ = ChronoClockNow(); - start_cpu_time_ = ThreadCPUUsage(); - } - - // Called by each thread - void StopTimer() { - CHECK(running_); - running_ = false; - real_time_used_ += ChronoClockNow() - start_real_time_; - // Floating point error can result in the subtraction producing a negative - // time. Guard against that. - cpu_time_used_ += std::max(ThreadCPUUsage() - start_cpu_time_, 0); - } - - // Called by each thread - void SetIterationTime(double seconds) { manual_time_used_ += seconds; } - - bool running() const { return running_; } - - // REQUIRES: timer is not running - double real_time_used() { - CHECK(!running_); - return real_time_used_; - } - - // REQUIRES: timer is not running - double cpu_time_used() { - CHECK(!running_); - return cpu_time_used_; - } - - // REQUIRES: timer is not running - double manual_time_used() { - CHECK(!running_); - return manual_time_used_; - } - - private: - bool running_ = false; // Is the timer running - double start_real_time_ = 0; // If running_ - double start_cpu_time_ = 0; // If running_ - - // Accumulated time so far (does not contain current slice if running_) - double real_time_used_ = 0; - double cpu_time_used_ = 0; - // Manually set iteration time. User sets this with SetIterationTime(seconds). - double manual_time_used_ = 0; -}; - namespace { BenchmarkReporter::Run CreateRunReport( const benchmark::internal::Benchmark::Instance& b, - const internal::ThreadManager::Result& results, size_t iters, - double seconds) { + const internal::ThreadManager::Result& results, double seconds) { // Create report about this benchmark run. BenchmarkReporter::Run report; @@ -228,8 +123,8 @@ BenchmarkReporter::Run CreateRunReport( report.error_occurred = results.has_error_; report.error_message = results.error_message_; report.report_label = results.report_label_; - // Report the total iterations across all threads. - report.iterations = static_cast(iters) * b.threads; + // This is the total iterations across all threads. + report.iterations = results.iterations; report.time_unit = b.time_unit; if (!report.error_occurred) { @@ -255,7 +150,7 @@ BenchmarkReporter::Run CreateRunReport( report.complexity_lambda = b.complexity_lambda; report.statistics = b.statistics; report.counters = results.counters; - internal::Finish(&report.counters, seconds, b.threads); + internal::Finish(&report.counters, results.iterations, seconds, b.threads); } return report; } @@ -268,11 +163,12 @@ void RunInThread(const benchmark::internal::Benchmark::Instance* b, internal::ThreadTimer timer; State st(iters, b->arg, thread_id, b->threads, &timer, manager); b->benchmark->Run(st); - CHECK(st.iterations() == st.max_iterations) + 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(); @@ -337,21 +233,23 @@ std::vector RunBenchmark( 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 + || has_explicit_iteration_count // An exact iteration count was requested || results.has_error_ - || iters >= kMaxIterations - || seconds >= min_time // the elapsed time is large enough + || 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, iters, seconds); + BenchmarkReporter::Run report = CreateRunReport(b, results, seconds); if (!report.error_occurred && b.complexity != oNone) complexity_reports->push_back(report); reports.push_back(report); @@ -394,26 +292,50 @@ std::vector RunBenchmark( } // namespace } // namespace internal -State::State(size_t max_iters, const std::vector& ranges, int thread_i, +State::State(size_t max_iters, const std::vector& ranges, int thread_i, int n_threads, internal::ThreadTimer* timer, internal::ThreadManager* manager) - : started_(false), + : total_iterations_(0), + batch_leftover_(0), + max_iterations(max_iters), + started_(false), finished_(false), - total_iterations_(max_iters + 1), + error_occurred_(false), range_(ranges), bytes_processed_(0), items_processed_(0), complexity_n_(0), - error_occurred_(false), counters(), thread_index(thread_i), threads(n_threads), - max_iterations(max_iters), timer_(timer), manager_(manager) { CHECK(max_iterations != 0) << "At least one iteration must be run"; - CHECK(total_iterations_ != 0) << "max iterations wrapped around"; CHECK_LT(thread_index, threads) << "thread_index must be less than threads"; + + // Note: The use of offsetof below is technically undefined until C++17 + // because State is not a standard layout type. However, all compilers + // currently provide well-defined behavior as an extension (which is + // demonstrated since constexpr evaluation must diagnose all undefined + // behavior). However, GCC and Clang also warn about this use of offsetof, + // which must be suppressed. +#if defined(__INTEL_COMPILER) +#pragma warning push +#pragma warning(disable:1875) +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Winvalid-offsetof" +#endif + // Offset tests to ensure commonly accessed data is on the first cache line. + const int cache_line_size = 64; + static_assert(offsetof(State, error_occurred_) <= + (cache_line_size - sizeof(error_occurred_)), + ""); +#if defined(__INTEL_COMPILER) +#pragma warning pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif } void State::PauseTiming() { @@ -437,7 +359,7 @@ void State::SkipWithError(const char* msg) { manager_->results.has_error_ = true; } } - total_iterations_ = 1; + total_iterations_ = 0; if (timer_->running()) timer_->StopTimer(); } @@ -453,6 +375,7 @@ void State::SetLabel(const char* label) { void State::StartKeepRunning() { CHECK(!started_ && !finished_); started_ = true; + total_iterations_ = error_occurred_ ? 0 : max_iterations; manager_->StartStopBarrier(); if (!error_occurred_) ResumeTiming(); } @@ -462,8 +385,8 @@ void State::FinishKeepRunning() { if (!error_occurred_) { PauseTiming(); } - // Total iterations has now wrapped around zero. Fix this. - total_iterations_ = 1; + // Total iterations has now wrapped around past 0. Fix this. + total_iterations_ = 0; finished_ = true; manager_->StartStopBarrier(); } @@ -472,8 +395,8 @@ namespace internal { namespace { void RunBenchmarks(const std::vector& benchmarks, - BenchmarkReporter* console_reporter, - BenchmarkReporter* file_reporter) { + BenchmarkReporter* console_reporter, + BenchmarkReporter* file_reporter) { // Note the file_reporter can be null. CHECK(console_reporter != nullptr); @@ -486,7 +409,7 @@ void RunBenchmarks(const std::vector& benchmarks, std::max(name_field_width, benchmark.name.size()); has_repetitions |= benchmark.repetitions > 1; - for(const auto& Stat : *benchmark.statistics) + for (const auto& Stat : *benchmark.statistics) stat_field_width = std::max(stat_field_width, Stat.name_.size()); } if (has_repetitions) name_field_width += 1 + stat_field_width; @@ -495,7 +418,7 @@ void RunBenchmarks(const std::vector& benchmarks, BenchmarkReporter::Context context; context.name_field_width = name_field_width; - // Keep track of runing times of all instances of current benchmark + // Keep track of running times of all instances of current benchmark std::vector complexity_reports; // We flush streams after invoking reporter methods that write to them. This @@ -554,15 +477,15 @@ ConsoleReporter::OutputOptions GetOutputOptions(bool force_no_color) { } else { output_opts &= ~ConsoleReporter::OO_Color; } - if(force_no_color) { + if (force_no_color) { output_opts &= ~ConsoleReporter::OO_Color; } - if(FLAGS_benchmark_counters_tabular) { + if (FLAGS_benchmark_counters_tabular) { output_opts |= ConsoleReporter::OO_Tabular; } else { output_opts &= ~ConsoleReporter::OO_Tabular; } - return static_cast< ConsoleReporter::OutputOptions >(output_opts); + return static_cast(output_opts); } } // end namespace internal @@ -587,7 +510,7 @@ size_t RunSpecifiedBenchmarks(BenchmarkReporter* console_reporter, std::unique_ptr default_file_reporter; if (!console_reporter) { default_console_reporter = internal::CreateReporter( - FLAGS_benchmark_format, internal::GetOutputOptions()); + FLAGS_benchmark_format, internal::GetOutputOptions()); console_reporter = default_console_reporter.get(); } auto& Out = console_reporter->GetOutputStream(); @@ -653,6 +576,8 @@ void PrintUsageAndExit() { void ParseCommandLineFlags(int* argc, char** argv) { using namespace benchmark; + BenchmarkReporter::Context::executable_name = + (argc && *argc > 0) ? argv[0] : "unknown"; for (int i = 1; i < *argc; ++i) { if (ParseBoolFlag(argv[i], "benchmark_list_tests", &FLAGS_benchmark_list_tests) || @@ -672,7 +597,7 @@ void ParseCommandLineFlags(int* argc, char** argv) { // TODO: Remove this. ParseStringFlag(argv[i], "color_print", &FLAGS_benchmark_color) || ParseBoolFlag(argv[i], "benchmark_counters_tabular", - &FLAGS_benchmark_counters_tabular) || + &FLAGS_benchmark_counters_tabular) || ParseInt32Flag(argv[i], "v", &FLAGS_v)) { for (int j = i; j != *argc - 1; ++j) argv[j] = argv[j + 1]; @@ -706,7 +631,8 @@ void Initialize(int* argc, char** argv) { bool ReportUnrecognizedArguments(int argc, char** argv) { for (int i = 1; i < argc; ++i) { - fprintf(stderr, "%s: error: unrecognized command-line flag: %s\n", argv[0], argv[i]); + fprintf(stderr, "%s: error: unrecognized command-line flag: %s\n", argv[0], + argv[i]); } return argc > 1; } diff --git a/utils/google-benchmark/src/benchmark_api_internal.h b/utils/google-benchmark/src/benchmark_api_internal.h index d481dc528..dd7a3ffe8 100644 --- a/utils/google-benchmark/src/benchmark_api_internal.h +++ b/utils/google-benchmark/src/benchmark_api_internal.h @@ -17,7 +17,7 @@ struct Benchmark::Instance { std::string name; Benchmark* benchmark; ReportMode report_mode; - std::vector arg; + std::vector arg; TimeUnit time_unit; int range_multiplier; bool use_real_time; diff --git a/utils/google-benchmark/src/benchmark_main.cc b/utils/google-benchmark/src/benchmark_main.cc new file mode 100644 index 000000000..b3b247831 --- /dev/null +++ b/utils/google-benchmark/src/benchmark_main.cc @@ -0,0 +1,17 @@ +// Copyright 2018 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/benchmark.h" + +BENCHMARK_MAIN(); diff --git a/utils/google-benchmark/src/benchmark_register.cc b/utils/google-benchmark/src/benchmark_register.cc index d5746a363..26a89721c 100644 --- a/utils/google-benchmark/src/benchmark_register.cc +++ b/utils/google-benchmark/src/benchmark_register.cc @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "benchmark/benchmark.h" -#include "benchmark_api_internal.h" -#include "internal_macros.h" +#include "benchmark_register.h" #ifndef BENCHMARK_OS_WINDOWS +#ifndef BENCHMARK_OS_FUCHSIA #include +#endif #include #include #endif @@ -34,13 +34,16 @@ #include #include +#include "benchmark/benchmark.h" +#include "benchmark_api_internal.h" #include "check.h" #include "commandlineflags.h" #include "complexity.h" -#include "statistics.h" +#include "internal_macros.h" #include "log.h" #include "mutex.h" #include "re.h" +#include "statistics.h" #include "string_util.h" #include "timers.h" @@ -74,7 +77,7 @@ class BenchmarkFamilies { // Extract the list of benchmark instances that match the specified // regular expression. - bool FindBenchmarks(const std::string& re, + bool FindBenchmarks(std::string re, std::vector* benchmarks, std::ostream* Err); @@ -104,13 +107,18 @@ void BenchmarkFamilies::ClearBenchmarks() { } bool BenchmarkFamilies::FindBenchmarks( - const std::string& spec, std::vector* benchmarks, + std::string spec, std::vector* benchmarks, std::ostream* ErrStream) { CHECK(ErrStream); auto& Err = *ErrStream; // Make regular expression out of command-line flag std::string error_msg; Regex re; + bool isNegativeFilter = false; + if (spec[0] == '-') { + spec.replace(0, 1, ""); + isNegativeFilter = true; + } if (!re.Init(spec, &error_msg)) { Err << "Could not compile benchmark re: " << error_msg << std::endl; return false; @@ -170,20 +178,20 @@ bool BenchmarkFamilies::FindBenchmarks( const auto& arg_name = family->arg_names_[arg_i]; if (!arg_name.empty()) { instance.name += - StringPrintF("%s:", family->arg_names_[arg_i].c_str()); + StrFormat("%s:", family->arg_names_[arg_i].c_str()); } } - - instance.name += StringPrintF("%d", arg); + + instance.name += StrFormat("%d", arg); ++arg_i; } if (!IsZero(family->min_time_)) - instance.name += StringPrintF("/min_time:%0.3f", family->min_time_); + instance.name += StrFormat("/min_time:%0.3f", family->min_time_); if (family->iterations_ != 0) - instance.name += StringPrintF("/iterations:%d", family->iterations_); + instance.name += StrFormat("/iterations:%d", family->iterations_); if (family->repetitions_ != 0) - instance.name += StringPrintF("/repeats:%d", family->repetitions_); + instance.name += StrFormat("/repeats:%d", family->repetitions_); if (family->use_manual_time_) { instance.name += "/manual_time"; @@ -193,10 +201,11 @@ bool BenchmarkFamilies::FindBenchmarks( // Add the number of threads used to the name if (!family->thread_counts_.empty()) { - instance.name += StringPrintF("/threads:%d", instance.threads); + instance.name += StrFormat("/threads:%d", instance.threads); } - if (re.Match(instance.name)) { + if ((re.Match(instance.name) && !isNegativeFilter) || + (!re.Match(instance.name) && isNegativeFilter)) { instance.last_benchmark_instance = (&args == &family->args_.back()); benchmarks->push_back(std::move(instance)); } @@ -244,30 +253,7 @@ Benchmark::Benchmark(const char* name) Benchmark::~Benchmark() {} -void Benchmark::AddRange(std::vector* dst, int lo, int hi, int mult) { - CHECK_GE(lo, 0); - CHECK_GE(hi, lo); - CHECK_GE(mult, 2); - - // Add "lo" - dst->push_back(lo); - - static const int kint32max = std::numeric_limits::max(); - - // Now space out the benchmarks in multiples of "mult" - for (int32_t i = 1; i < kint32max / mult; i *= mult) { - if (i >= hi) break; - if (i > lo) { - dst->push_back(i); - } - } - // Add "hi" (if different from "lo") - if (hi != lo) { - dst->push_back(hi); - } -} - -Benchmark* Benchmark::Arg(int x) { +Benchmark* Benchmark::Arg(int64_t x) { CHECK(ArgsCnt() == -1 || ArgsCnt() == 1); args_.push_back({x}); return this; @@ -278,20 +264,21 @@ Benchmark* Benchmark::Unit(TimeUnit unit) { return this; } -Benchmark* Benchmark::Range(int start, int limit) { +Benchmark* Benchmark::Range(int64_t start, int64_t limit) { CHECK(ArgsCnt() == -1 || ArgsCnt() == 1); - std::vector arglist; + std::vector arglist; AddRange(&arglist, start, limit, range_multiplier_); - for (int i : arglist) { + for (int64_t i : arglist) { args_.push_back({i}); } return this; } -Benchmark* Benchmark::Ranges(const std::vector>& ranges) { +Benchmark* Benchmark::Ranges( + const std::vector>& ranges) { CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast(ranges.size())); - std::vector> arglists(ranges.size()); + std::vector> arglists(ranges.size()); std::size_t total = 1; for (std::size_t i = 0; i < ranges.size(); i++) { AddRange(&arglists[i], ranges[i].first, ranges[i].second, @@ -302,7 +289,7 @@ Benchmark* Benchmark::Ranges(const std::vector>& ranges) { std::vector ctr(arglists.size(), 0); for (std::size_t i = 0; i < total; i++) { - std::vector tmp; + std::vector tmp; tmp.reserve(arglists.size()); for (std::size_t j = 0; j < arglists.size(); j++) { @@ -334,17 +321,17 @@ Benchmark* Benchmark::ArgNames(const std::vector& names) { return this; } -Benchmark* Benchmark::DenseRange(int start, int limit, int step) { +Benchmark* Benchmark::DenseRange(int64_t start, int64_t limit, int step) { CHECK(ArgsCnt() == -1 || ArgsCnt() == 1); CHECK_GE(start, 0); CHECK_LE(start, limit); - for (int arg = start; arg <= limit; arg += step) { + for (int64_t arg = start; arg <= limit; arg += step) { args_.push_back({arg}); } return this; } -Benchmark* Benchmark::Args(const std::vector& args) { +Benchmark* Benchmark::Args(const std::vector& args) { CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast(args.size())); args_.push_back(args); return this; @@ -361,7 +348,6 @@ Benchmark* Benchmark::RangeMultiplier(int multiplier) { return this; } - Benchmark* Benchmark::MinTime(double t) { CHECK(t > 0.0); CHECK(iterations_ == 0); @@ -369,7 +355,6 @@ Benchmark* Benchmark::MinTime(double t) { return this; } - Benchmark* Benchmark::Iterations(size_t n) { CHECK(n > 0); CHECK(IsZero(min_time_)); diff --git a/utils/google-benchmark/src/benchmark_register.h b/utils/google-benchmark/src/benchmark_register.h new file mode 100644 index 000000000..0705e219f --- /dev/null +++ b/utils/google-benchmark/src/benchmark_register.h @@ -0,0 +1,33 @@ +#ifndef BENCHMARK_REGISTER_H +#define BENCHMARK_REGISTER_H + +#include + +#include "check.h" + +template +void AddRange(std::vector* dst, T lo, T hi, int mult) { + CHECK_GE(lo, 0); + CHECK_GE(hi, lo); + CHECK_GE(mult, 2); + + // Add "lo" + dst->push_back(lo); + + static const T kmax = std::numeric_limits::max(); + + // Now space out the benchmarks in multiples of "mult" + for (T i = 1; i < kmax / mult; i *= mult) { + if (i >= hi) break; + if (i > lo) { + dst->push_back(i); + } + } + + // Add "hi" (if different from "lo") + if (hi != lo) { + dst->push_back(hi); + } +} + +#endif // BENCHMARK_REGISTER_H diff --git a/utils/google-benchmark/src/check.h b/utils/google-benchmark/src/check.h index 73bead2fb..f5f8253f8 100644 --- a/utils/google-benchmark/src/check.h +++ b/utils/google-benchmark/src/check.h @@ -1,9 +1,9 @@ #ifndef CHECK_H_ #define CHECK_H_ +#include #include #include -#include #include "internal_macros.h" #include "log.h" @@ -62,6 +62,8 @@ class CheckHandler { #define CHECK(b) ::benchmark::internal::GetNullLogInstance() #endif +// clang-format off +// preserve whitespacing between operators for alignment #define CHECK_EQ(a, b) CHECK((a) == (b)) #define CHECK_NE(a, b) CHECK((a) != (b)) #define CHECK_GE(a, b) CHECK((a) >= (b)) @@ -75,5 +77,6 @@ class CheckHandler { #define CHECK_FLOAT_LE(a, b, eps) CHECK((b) - (a) > -(eps)) #define CHECK_FLOAT_GT(a, b, eps) CHECK((a) - (b) > (eps)) #define CHECK_FLOAT_LT(a, b, eps) CHECK((b) - (a) > (eps)) +//clang-format on #endif // CHECK_H_ diff --git a/utils/google-benchmark/src/commandlineflags.cc b/utils/google-benchmark/src/commandlineflags.cc index 2fc92517a..734e88bbe 100644 --- a/utils/google-benchmark/src/commandlineflags.cc +++ b/utils/google-benchmark/src/commandlineflags.cc @@ -45,7 +45,7 @@ bool ParseInt32(const std::string& src_text, const char* str, int32_t* value) { // LONG_MAX or LONG_MIN when the input overflows.) result != long_value // The parsed value overflows as an Int32. - ) { + ) { std::cerr << src_text << " is expected to be a 32-bit integer, " << "but actually has value \"" << str << "\", " << "which overflows.\n"; diff --git a/utils/google-benchmark/src/complexity.cc b/utils/google-benchmark/src/complexity.cc index 88832698e..aafd538df 100644 --- a/utils/google-benchmark/src/complexity.cc +++ b/utils/google-benchmark/src/complexity.cc @@ -26,20 +26,23 @@ namespace benchmark { // Internal function to calculate the different scalability forms BigOFunc* FittingCurve(BigO complexity) { + static const double kLog2E = 1.44269504088896340736; switch (complexity) { case oN: - return [](int n) -> double { return n; }; + return [](int64_t n) -> double { return static_cast(n); }; case oNSquared: - return [](int n) -> double { return std::pow(n, 2); }; + return [](int64_t n) -> double { return std::pow(n, 2); }; case oNCubed: - return [](int n) -> double { return std::pow(n, 3); }; + return [](int64_t n) -> double { return std::pow(n, 3); }; case oLogN: - return [](int n) { return log2(n); }; + /* Note: can't use log2 because Android's GNU STL lacks it */ + return [](int64_t n) { return kLog2E * log(static_cast(n)); }; case oNLogN: - return [](int n) { return n * log2(n); }; + /* Note: can't use log2 because Android's GNU STL lacks it */ + return [](int64_t n) { return kLog2E * n * log(static_cast(n)); }; case o1: default: - return [](int) { return 1.0; }; + return [](int64_t) { return 1.0; }; } } @@ -65,15 +68,15 @@ std::string GetBigOString(BigO complexity) { // Find the coefficient for the high-order term in the running time, by // minimizing the sum of squares of relative error, for the fitting curve -// given by the lambda expresion. +// given by the lambda expression. // - n : Vector containing the size of the benchmark tests. // - time : Vector containing the times for the benchmark tests. -// - fitting_curve : lambda expresion (e.g. [](int n) {return n; };). +// - 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 -LeastSq MinimalLeastSq(const std::vector& n, +LeastSq MinimalLeastSq(const std::vector& n, const std::vector& time, BigOFunc* fitting_curve) { double sigma_gn = 0.0; @@ -117,7 +120,7 @@ LeastSq MinimalLeastSq(const std::vector& n, // - complexity : If different than oAuto, the fitting curve will stick to // this one. If it is oAuto, it will be calculated the best // fitting curve. -LeastSq MinimalLeastSq(const std::vector& n, +LeastSq MinimalLeastSq(const std::vector& n, const std::vector& time, const BigO complexity) { CHECK_EQ(n.size(), time.size()); CHECK_GE(n.size(), 2); // Do not compute fitting curve is less than two @@ -157,7 +160,7 @@ std::vector ComputeBigO( if (reports.size() < 2) return results; // Accumulators. - std::vector n; + std::vector n; std::vector real_time; std::vector cpu_time; diff --git a/utils/google-benchmark/src/counter.cc b/utils/google-benchmark/src/counter.cc index ed1aa044e..cb604e060 100644 --- a/utils/google-benchmark/src/counter.cc +++ b/utils/google-benchmark/src/counter.cc @@ -17,7 +17,8 @@ namespace benchmark { namespace internal { -double Finish(Counter const& c, double cpu_time, double num_threads) { +double Finish(Counter const& c, int64_t iterations, double cpu_time, + double num_threads) { double v = c.value; if (c.flags & Counter::kIsRate) { v /= cpu_time; @@ -25,25 +26,31 @@ double Finish(Counter const& c, double cpu_time, double num_threads) { if (c.flags & Counter::kAvgThreads) { v /= num_threads; } + if (c.flags & Counter::kIsIterationInvariant) { + v *= iterations; + } + if (c.flags & Counter::kAvgIterations) { + v /= iterations; + } return v; } -void Finish(UserCounters *l, double cpu_time, double num_threads) { - for (auto &c : *l) { - c.second.value = Finish(c.second, cpu_time, num_threads); +void Finish(UserCounters* l, int64_t iterations, double cpu_time, double num_threads) { + for (auto& c : *l) { + c.second.value = Finish(c.second, iterations, cpu_time, num_threads); } } -void Increment(UserCounters *l, UserCounters const& r) { +void Increment(UserCounters* l, UserCounters const& r) { // add counters present in both or just in *l - for (auto &c : *l) { + for (auto& c : *l) { auto it = r.find(c.first); if (it != r.end()) { c.second.value = c.second + it->second; } } // add counters present in r, but not in *l - for (auto const &tc : r) { + for (auto const& tc : r) { auto it = l->find(tc.first); if (it == l->end()) { (*l)[tc.first] = tc.second; @@ -64,5 +71,5 @@ bool SameNames(UserCounters const& l, UserCounters const& r) { return true; } -} // end namespace internal -} // end namespace benchmark +} // end namespace internal +} // end namespace benchmark diff --git a/utils/google-benchmark/src/counter.h b/utils/google-benchmark/src/counter.h index dd6865a31..d884e50aa 100644 --- a/utils/google-benchmark/src/counter.h +++ b/utils/google-benchmark/src/counter.h @@ -18,9 +18,9 @@ namespace benchmark { // these counter-related functions are hidden to reduce API surface. namespace internal { -void Finish(UserCounters *l, double time, double num_threads); -void Increment(UserCounters *l, UserCounters const& r); +void Finish(UserCounters* l, int64_t iterations, double time, double num_threads); +void Increment(UserCounters* l, UserCounters const& r); bool SameNames(UserCounters const& l, UserCounters const& r); -} // end namespace internal +} // end namespace internal -} //end namespace benchmark +} // end namespace benchmark diff --git a/utils/google-benchmark/src/csv_reporter.cc b/utils/google-benchmark/src/csv_reporter.cc index 35510645b..4a641909d 100644 --- a/utils/google-benchmark/src/csv_reporter.cc +++ b/utils/google-benchmark/src/csv_reporter.cc @@ -22,9 +22,9 @@ #include #include +#include "check.h" #include "string_util.h" #include "timers.h" -#include "check.h" // File format reference: http://edoceo.com/utilitas/csv-file-format. @@ -42,7 +42,7 @@ bool CSVReporter::ReportContext(const Context& context) { return true; } -void CSVReporter::ReportRuns(const std::vector & reports) { +void CSVReporter::ReportRuns(const std::vector& reports) { std::ostream& Out = GetOutputStream(); if (!printed_header_) { @@ -58,7 +58,8 @@ void CSVReporter::ReportRuns(const std::vector & reports) { Out << *B++; if (B != elements.end()) Out << ","; } - for (auto B = user_counter_names_.begin(); B != user_counter_names_.end();) { + for (auto B = user_counter_names_.begin(); + B != user_counter_names_.end();) { Out << ",\"" << *B++ << "\""; } Out << "\n"; @@ -69,9 +70,9 @@ void CSVReporter::ReportRuns(const std::vector & reports) { for (const auto& run : reports) { for (const auto& cnt : run.counters) { CHECK(user_counter_names_.find(cnt.first) != user_counter_names_.end()) - << "All counters must be present in each run. " - << "Counter named \"" << cnt.first - << "\" was not in a run after being added to the header"; + << "All counters must be present in each run. " + << "Counter named \"" << cnt.first + << "\" was not in a run after being added to the header"; } } } @@ -80,10 +81,9 @@ void CSVReporter::ReportRuns(const std::vector & reports) { for (const auto& run : reports) { PrintRunData(run); } - } -void CSVReporter::PrintRunData(const Run & run) { +void CSVReporter::PrintRunData(const Run& run) { std::ostream& Out = GetOutputStream(); // Field with embedded double-quote characters must be doubled and the field @@ -135,9 +135,9 @@ void CSVReporter::PrintRunData(const Run & run) { Out << ",,"; // for error_occurred and error_message // Print user counters - for (const auto &ucn : user_counter_names_) { + for (const auto& ucn : user_counter_names_) { auto it = run.counters.find(ucn); - if(it == run.counters.end()) { + if (it == run.counters.end()) { Out << ","; } else { Out << "," << it->second; diff --git a/utils/google-benchmark/src/cycleclock.h b/utils/google-benchmark/src/cycleclock.h index 4251fe4c3..00d576416 100644 --- a/utils/google-benchmark/src/cycleclock.h +++ b/utils/google-benchmark/src/cycleclock.h @@ -121,7 +121,7 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { // because is provides nanosecond resolution (which is noticable at // least for PNaCl modules running on x86 Mac & Linux). // Initialize to always return 0 if clock_gettime fails. - struct timespec ts = { 0, 0 }; + struct timespec ts = {0, 0}; clock_gettime(CLOCK_MONOTONIC, &ts); return static_cast(ts.tv_sec) * 1000000000 + ts.tv_nsec; #elif defined(__aarch64__) @@ -159,6 +159,11 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { struct timeval tv; gettimeofday(&tv, nullptr); return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; +#elif defined(__s390__) // Covers both s390 and s390x. + // Return the CPU clock. + uint64_t tsc; + asm("stck %0" : "=Q"(tsc) : : "cc"); + return tsc; #else // The soft failover to a generic implementation is automatic only for ARM. // For other platforms the developer is expected to make an attempt to create diff --git a/utils/google-benchmark/src/internal_macros.h b/utils/google-benchmark/src/internal_macros.h index c34f5716e..b7e9203ff 100644 --- a/utils/google-benchmark/src/internal_macros.h +++ b/utils/google-benchmark/src/internal_macros.h @@ -3,6 +3,11 @@ #include "benchmark/benchmark.h" +/* Needed to detect STL */ +#include + +// clang-format off + #ifndef __has_feature #define __has_feature(x) 0 #endif @@ -39,6 +44,7 @@ #elif defined(_WIN32) #define BENCHMARK_OS_WINDOWS 1 #elif defined(__APPLE__) + #define BENCHMARK_OS_APPLE 1 #include "TargetConditionals.h" #if defined(TARGET_OS_MAC) #define BENCHMARK_OS_MACOSX 1 @@ -50,14 +56,24 @@ #define BENCHMARK_OS_FREEBSD 1 #elif defined(__NetBSD__) #define BENCHMARK_OS_NETBSD 1 +#elif defined(__OpenBSD__) + #define BENCHMARK_OS_OPENBSD 1 #elif defined(__linux__) #define BENCHMARK_OS_LINUX 1 #elif defined(__native_client__) #define BENCHMARK_OS_NACL 1 -#elif defined(EMSCRIPTEN) +#elif defined(__EMSCRIPTEN__) #define BENCHMARK_OS_EMSCRIPTEN 1 #elif defined(__rtems__) #define BENCHMARK_OS_RTEMS 1 +#elif defined(__Fuchsia__) +#define BENCHMARK_OS_FUCHSIA 1 +#elif defined (__SVR4) && defined (__sun) +#define BENCHMARK_OS_SOLARIS 1 +#endif + +#if defined(__ANDROID__) && defined(__GLIBCXX__) +#define BENCHMARK_STL_ANDROID_GNUSTL 1 #endif #if !__has_feature(cxx_exceptions) && !defined(__cpp_exceptions) \ @@ -79,4 +95,6 @@ #define BENCHMARK_UNREACHABLE() ((void)0) #endif +// clang-format on + #endif // BENCHMARK_INTERNAL_MACROS_H_ diff --git a/utils/google-benchmark/src/json_reporter.cc b/utils/google-benchmark/src/json_reporter.cc index b5ae302ad..611605af6 100644 --- a/utils/google-benchmark/src/json_reporter.cc +++ b/utils/google-benchmark/src/json_reporter.cc @@ -17,12 +17,12 @@ #include #include +#include // for setprecision #include +#include #include #include #include -#include // for setprecision -#include #include "string_util.h" #include "timers.h" @@ -32,15 +32,15 @@ namespace benchmark { namespace { std::string FormatKV(std::string const& key, std::string const& value) { - return StringPrintF("\"%s\": \"%s\"", key.c_str(), value.c_str()); + return StrFormat("\"%s\": \"%s\"", key.c_str(), value.c_str()); } std::string FormatKV(std::string const& key, const char* value) { - return StringPrintF("\"%s\": \"%s\"", key.c_str(), value); + return StrFormat("\"%s\": \"%s\"", key.c_str(), value); } std::string FormatKV(std::string const& key, bool value) { - return StringPrintF("\"%s\": %s", key.c_str(), value ? "true" : "false"); + return StrFormat("\"%s\": %s", key.c_str(), value ? "true" : "false"); } std::string FormatKV(std::string const& key, int64_t value) { @@ -53,7 +53,7 @@ std::string FormatKV(std::string const& key, double value) { std::stringstream ss; ss << '"' << key << "\": "; - const auto max_digits10 = std::numeric_limits::max_digits10; + const auto max_digits10 = std::numeric_limits::max_digits10; const auto max_fractional_digits10 = max_digits10 - 1; ss << std::scientific << std::setprecision(max_fractional_digits10) << value; @@ -77,6 +77,10 @@ bool JSONReporter::ReportContext(const Context& context) { std::string walltime_value = LocalDateTimeString(); out << indent << FormatKV("date", walltime_value) << ",\n"; + if (Context::executable_name) { + out << indent << FormatKV("executable", Context::executable_name) << ",\n"; + } + CPUInfo const& info = context.cpu_info; out << indent << FormatKV("num_cpus", static_cast(info.num_cpus)) << ",\n"; @@ -157,40 +161,30 @@ void JSONReporter::PrintRunData(Run const& run) { } if (!run.report_big_o && !run.report_rms) { out << indent << FormatKV("iterations", run.iterations) << ",\n"; - out << indent - << FormatKV("real_time", run.GetAdjustedRealTime()) - << ",\n"; - out << indent - << FormatKV("cpu_time", run.GetAdjustedCPUTime()); + out << indent << FormatKV("real_time", run.GetAdjustedRealTime()) << ",\n"; + out << indent << FormatKV("cpu_time", run.GetAdjustedCPUTime()); out << ",\n" << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit)); } else if (run.report_big_o) { - out << indent - << FormatKV("cpu_coefficient", run.GetAdjustedCPUTime()) + out << indent << FormatKV("cpu_coefficient", run.GetAdjustedCPUTime()) << ",\n"; - out << indent - << FormatKV("real_coefficient", run.GetAdjustedRealTime()) + out << indent << FormatKV("real_coefficient", run.GetAdjustedRealTime()) << ",\n"; out << indent << FormatKV("big_o", GetBigOString(run.complexity)) << ",\n"; out << indent << FormatKV("time_unit", GetTimeUnitString(run.time_unit)); } else if (run.report_rms) { - out << indent - << FormatKV("rms", run.GetAdjustedCPUTime()); + out << indent << FormatKV("rms", run.GetAdjustedCPUTime()); } if (run.bytes_per_second > 0.0) { out << ",\n" - << indent - << FormatKV("bytes_per_second", run.bytes_per_second); + << 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); + << indent << FormatKV("items_per_second", run.items_per_second); } - for(auto &c : run.counters) { - out << ",\n" - << indent - << FormatKV(c.first, c.second); + for (auto& c : run.counters) { + out << ",\n" << indent << FormatKV(c.first, c.second); } if (!run.report_label.empty()) { out << ",\n" << indent << FormatKV("label", run.report_label); @@ -198,4 +192,4 @@ void JSONReporter::PrintRunData(Run const& run) { out << '\n'; } -} // end namespace benchmark +} // end namespace benchmark diff --git a/utils/google-benchmark/src/log.h b/utils/google-benchmark/src/log.h index d06e1031d..47d0c35c0 100644 --- a/utils/google-benchmark/src/log.h +++ b/utils/google-benchmark/src/log.h @@ -66,8 +66,9 @@ inline LogType& GetLogInstanceForLevel(int level) { } // end namespace internal } // end namespace benchmark +// clang-format off #define VLOG(x) \ (::benchmark::internal::GetLogInstanceForLevel(x) << "-- LOG(" << x << "):" \ " ") - +// clang-format on #endif diff --git a/utils/google-benchmark/src/re.h b/utils/google-benchmark/src/re.h index 01e973650..fbe25037b 100644 --- a/utils/google-benchmark/src/re.h +++ b/utils/google-benchmark/src/re.h @@ -17,22 +17,39 @@ #include "internal_macros.h" +// clang-format off + +#if !defined(HAVE_STD_REGEX) && \ + !defined(HAVE_GNU_POSIX_REGEX) && \ + !defined(HAVE_POSIX_REGEX) + // No explicit regex selection; detect based on builtin hints. + #if defined(BENCHMARK_OS_LINUX) || defined(BENCHMARK_OS_APPLE) + #define HAVE_POSIX_REGEX 1 + #elif __cplusplus >= 199711L + #define HAVE_STD_REGEX 1 + #endif +#endif + // Prefer C regex libraries when compiling w/o exceptions so that we can // correctly report errors. -#if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && defined(HAVE_STD_REGEX) && \ +#if defined(BENCHMARK_HAS_NO_EXCEPTIONS) && \ + defined(BENCHMARK_HAVE_STD_REGEX) && \ (defined(HAVE_GNU_POSIX_REGEX) || defined(HAVE_POSIX_REGEX)) -#undef HAVE_STD_REGEX + #undef HAVE_STD_REGEX #endif #if defined(HAVE_STD_REGEX) -#include + #include #elif defined(HAVE_GNU_POSIX_REGEX) -#include + #include #elif defined(HAVE_POSIX_REGEX) -#include + #include #else #error No regular expression backend was found! #endif + +// clang-format on + #include #include "check.h" @@ -72,20 +89,21 @@ class Regex { inline bool Regex::Init(const std::string& spec, std::string* error) { #ifdef BENCHMARK_HAS_NO_EXCEPTIONS - ((void)error); // suppress unused warning + ((void)error); // suppress unused warning #else try { #endif - re_ = std::regex(spec, std::regex_constants::extended); - init_ = true; + re_ = std::regex(spec, std::regex_constants::extended); + init_ = true; #ifndef BENCHMARK_HAS_NO_EXCEPTIONS - } catch (const std::regex_error& e) { - if (error) { - *error = e.what(); - } +} +catch (const std::regex_error& e) { + if (error) { + *error = e.what(); } +} #endif - return init_; +return init_; } inline Regex::~Regex() {} diff --git a/utils/google-benchmark/src/reporter.cc b/utils/google-benchmark/src/reporter.cc index 5d2fa05a2..541661a25 100644 --- a/utils/google-benchmark/src/reporter.cc +++ b/utils/google-benchmark/src/reporter.cc @@ -37,6 +37,9 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out, Out << LocalDateTimeString() << "\n"; + if (context.executable_name) + Out << "Running " << context.executable_name << "\n"; + const CPUInfo &info = context.cpu_info; Out << "Run on (" << info.num_cpus << " X " << (info.cycles_per_second / 1000000.0) << " MHz CPU " @@ -64,6 +67,9 @@ void BenchmarkReporter::PrintBasicContext(std::ostream *out, #endif } +// No initializer because it's already initialized to NULL. +const char *BenchmarkReporter::Context::executable_name; + BenchmarkReporter::Context::Context() : cpu_info(CPUInfo::Get()) {} double BenchmarkReporter::Run::GetAdjustedRealTime() const { diff --git a/utils/google-benchmark/src/statistics.cc b/utils/google-benchmark/src/statistics.cc index 5932ad438..612dda2d1 100644 --- a/utils/google-benchmark/src/statistics.cc +++ b/utils/google-benchmark/src/statistics.cc @@ -17,9 +17,9 @@ #include #include +#include #include #include -#include #include "check.h" #include "statistics.h" @@ -30,22 +30,25 @@ auto StatisticsSum = [](const std::vector& v) { }; double StatisticsMean(const std::vector& v) { - if (v.size() == 0) return 0.0; + if (v.empty()) return 0.0; return StatisticsSum(v) * (1.0 / v.size()); } double StatisticsMedian(const std::vector& v) { if (v.size() < 3) return StatisticsMean(v); - std::vector partial; - // we need roundDown(count/2)+1 slots - partial.resize(1 + (v.size() / 2)); - std::partial_sort_copy(v.begin(), v.end(), partial.begin(), partial.end()); - // did we have odd number of samples? - // if yes, then the last element of partially-sorted vector is the median - // it no, then the average of the last two elements is the median - if(v.size() % 2 == 1) - return partial.back(); - return (partial[partial.size() - 2] + partial[partial.size() - 1]) / 2.0; + std::vector copy(v); + + auto center = copy.begin() + v.size() / 2; + std::nth_element(copy.begin(), center, copy.end()); + + // did we have an odd number of samples? + // if yes, then center is the median + // it no, then we are looking for the average between center and the value + // before + if (v.size() % 2 == 1) return *center; + auto center2 = copy.begin() + v.size() / 2 - 1; + std::nth_element(copy.begin(), center2, copy.end()); + return (*center + *center2) / 2.0; } // Return the sum of the squares of this sample set @@ -62,11 +65,10 @@ auto Sqrt = [](const double dat) { double StatisticsStdDev(const std::vector& v) { const auto mean = StatisticsMean(v); - if (v.size() == 0) return mean; + if (v.empty()) return mean; // Sample standard deviation is undefined for n = 1 - if (v.size() == 1) - return 0.0; + if (v.size() == 1) return 0.0; const double avg_squares = SumSquares(v) * (1.0 / v.size()); return Sqrt(v.size() / (v.size() - 1.0) * (avg_squares - Sqr(mean))); @@ -105,11 +107,11 @@ std::vector ComputeStats( Counter c; std::vector s; }; - std::map< std::string, CounterStat > counter_stats; - for(Run const& r : reports) { - for(auto const& cnt : r.counters) { + std::map counter_stats; + for (Run const& r : reports) { + for (auto const& cnt : r.counters) { auto it = counter_stats.find(cnt.first); - if(it == counter_stats.end()) { + if (it == counter_stats.end()) { counter_stats.insert({cnt.first, {cnt.second, std::vector{}}}); it = counter_stats.find(cnt.first); it->second.s.reserve(reports.size()); @@ -129,7 +131,7 @@ std::vector ComputeStats( 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) { + for (auto const& cnt : run.counters) { auto it = counter_stats.find(cnt.first); CHECK_NE(it, counter_stats.end()); it->second.s.emplace_back(cnt.second); @@ -145,7 +147,7 @@ std::vector ComputeStats( } } - for(const auto& Stat : *reports[0].statistics) { + 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_; @@ -160,7 +162,7 @@ std::vector ComputeStats( data.time_unit = reports[0].time_unit; // user counters - for(auto const& kv : counter_stats) { + for (auto const& kv : counter_stats) { const auto uc_stat = Stat.compute_(kv.second.s); auto c = Counter(uc_stat, counter_stats[kv.first].c.flags); data.counters[kv.first] = c; diff --git a/utils/google-benchmark/src/string_util.cc b/utils/google-benchmark/src/string_util.cc index 29edb2a46..05ac5b4ea 100644 --- a/utils/google-benchmark/src/string_util.cc +++ b/utils/google-benchmark/src/string_util.cc @@ -122,7 +122,7 @@ std::string HumanReadableNumber(double n, double one_k) { return ToBinaryStringFullySpecified(n, 1.1, 1, one_k); } -std::string StringPrintFImp(const char* msg, va_list args) { +std::string StrFormatImp(const char* msg, va_list args) { // we might need a second shot at this, so pre-emptivly make a copy va_list args_cp; va_copy(args_cp, args); @@ -152,10 +152,10 @@ std::string StringPrintFImp(const char* msg, va_list args) { return std::string(buff_ptr.get()); } -std::string StringPrintF(const char* format, ...) { +std::string StrFormat(const char* format, ...) { va_list args; va_start(args, format); - std::string tmp = StringPrintFImp(format, args); + std::string tmp = StrFormatImp(format, args); va_end(args); return tmp; } @@ -169,4 +169,93 @@ void ReplaceAll(std::string* str, const std::string& from, } } +#ifdef BENCHMARK_STL_ANDROID_GNUSTL +/* + * GNU STL in Android NDK lacks support for some C++11 functions, including + * stoul, stoi, stod. We reimplement them here using C functions strtoul, + * strtol, strtod. Note that reimplemented functions are in benchmark:: + * namespace, not std:: namespace. + */ +unsigned long stoul(const std::string& str, size_t* pos, int base) { + /* Record previous errno */ + const int oldErrno = errno; + errno = 0; + + const char* strStart = str.c_str(); + char* strEnd = const_cast(strStart); + const unsigned long result = strtoul(strStart, &strEnd, base); + + const int strtoulErrno = errno; + /* Restore previous errno */ + errno = oldErrno; + + /* Check for errors and return */ + if (strtoulErrno == ERANGE) { + throw std::out_of_range( + "stoul failed: " + str + " is outside of range of unsigned long"); + } else if (strEnd == strStart || strtoulErrno != 0) { + throw std::invalid_argument( + "stoul failed: " + str + " is not an integer"); + } + if (pos != nullptr) { + *pos = static_cast(strEnd - strStart); + } + return result; +} + +int stoi(const std::string& str, size_t* pos, int base) { + /* Record previous errno */ + const int oldErrno = errno; + errno = 0; + + const char* strStart = str.c_str(); + char* strEnd = const_cast(strStart); + const long result = strtol(strStart, &strEnd, base); + + const int strtolErrno = errno; + /* Restore previous errno */ + errno = oldErrno; + + /* Check for errors and return */ + if (strtolErrno == ERANGE || long(int(result)) != result) { + throw std::out_of_range( + "stoul failed: " + str + " is outside of range of int"); + } else if (strEnd == strStart || strtolErrno != 0) { + throw std::invalid_argument( + "stoul failed: " + str + " is not an integer"); + } + if (pos != nullptr) { + *pos = static_cast(strEnd - strStart); + } + return int(result); +} + +double stod(const std::string& str, size_t* pos) { + /* Record previous errno */ + const int oldErrno = errno; + errno = 0; + + const char* strStart = str.c_str(); + char* strEnd = const_cast(strStart); + const double result = strtod(strStart, &strEnd); + + /* Restore previous errno */ + const int strtodErrno = errno; + errno = oldErrno; + + /* Check for errors and return */ + if (strtodErrno == ERANGE) { + throw std::out_of_range( + "stoul failed: " + str + " is outside of range of int"); + } else if (strEnd == strStart || strtodErrno != 0) { + throw std::invalid_argument( + "stoul failed: " + str + " is not an integer"); + } + if (pos != nullptr) { + *pos = static_cast(strEnd - strStart); + } + return result; +} +#endif + } // end namespace benchmark diff --git a/utils/google-benchmark/src/string_util.h b/utils/google-benchmark/src/string_util.h index c3d53bfd3..4a5501273 100644 --- a/utils/google-benchmark/src/string_util.h +++ b/utils/google-benchmark/src/string_util.h @@ -12,29 +12,45 @@ void AppendHumanReadable(int n, std::string* str); std::string HumanReadableNumber(double n, double one_k = 1024.0); -std::string StringPrintF(const char* format, ...); +std::string StrFormat(const char* format, ...); -inline std::ostream& StringCatImp(std::ostream& out) BENCHMARK_NOEXCEPT { +inline std::ostream& StrCatImp(std::ostream& out) BENCHMARK_NOEXCEPT { return out; } template -inline std::ostream& StringCatImp(std::ostream& out, First&& f, - Rest&&... rest) { +inline std::ostream& StrCatImp(std::ostream& out, First&& f, Rest&&... rest) { out << std::forward(f); - return StringCatImp(out, std::forward(rest)...); + return StrCatImp(out, std::forward(rest)...); } template inline std::string StrCat(Args&&... args) { std::ostringstream ss; - StringCatImp(ss, std::forward(args)...); + StrCatImp(ss, std::forward(args)...); return ss.str(); } void ReplaceAll(std::string* str, const std::string& from, const std::string& to); +#ifdef BENCHMARK_STL_ANDROID_GNUSTL +/* + * GNU STL in Android NDK lacks support for some C++11 functions, including + * stoul, stoi, stod. We reimplement them here using C functions strtoul, + * strtol, strtod. Note that reimplemented functions are in benchmark:: + * namespace, not std:: namespace. + */ +unsigned long stoul(const std::string& str, size_t* pos = nullptr, + int base = 10); +int stoi(const std::string& str, size_t* pos = nullptr, int base = 10); +double stod(const std::string& str, size_t* pos = nullptr); +#else +using std::stoul; +using std::stoi; +using std::stod; +#endif + } // end namespace benchmark #endif // BENCHMARK_STRING_UTIL_H_ diff --git a/utils/google-benchmark/src/sysinfo.cc b/utils/google-benchmark/src/sysinfo.cc index 2520ad5ae..73064b97b 100644 --- a/utils/google-benchmark/src/sysinfo.cc +++ b/utils/google-benchmark/src/sysinfo.cc @@ -16,20 +16,26 @@ #ifdef BENCHMARK_OS_WINDOWS #include +#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA #include #include #else #include +#ifndef BENCHMARK_OS_FUCHSIA #include +#endif #include #include // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD #include #if defined BENCHMARK_OS_FREEBSD || defined BENCHMARK_OS_MACOSX || \ - defined BENCHMARK_OS_NETBSD + defined BENCHMARK_OS_NETBSD || defined BENCHMARK_OS_OPENBSD #define BENCHMARK_HAS_SYSCTL #include #endif #endif +#if defined(BENCHMARK_OS_SOLARIS) +#include +#endif #include #include @@ -130,6 +136,26 @@ struct ValueUnion { }; ValueUnion GetSysctlImp(std::string const& Name) { +#if defined BENCHMARK_OS_OPENBSD + int mib[2]; + + mib[0] = CTL_HW; + if ((Name == "hw.ncpu") || (Name == "hw.cpuspeed")){ + ValueUnion buff(sizeof(int)); + + if (Name == "hw.ncpu") { + mib[1] = HW_NCPU; + } else { + mib[1] = HW_CPUSPEED; + } + + if (sysctl(mib, 2, buff.data(), &buff.Size, nullptr, 0) == -1) { + return ValueUnion(); + } + return buff; + } + return ValueUnion(); +#else size_t CurBuffSize = 0; if (sysctlbyname(Name.c_str(), nullptr, &CurBuffSize, nullptr, 0) == -1) return ValueUnion(); @@ -138,6 +164,7 @@ ValueUnion GetSysctlImp(std::string const& Name) { if (sysctlbyname(Name.c_str(), buff.data(), &buff.Size, nullptr, 0) == 0) return buff; return ValueUnion(); +#endif } BENCHMARK_MAYBE_UNUSED @@ -198,7 +225,7 @@ int CountSetBitsInCPUMap(std::string Val) { auto CountBits = [](std::string Part) { using CPUMask = std::bitset; Part = "0x" + Part; - CPUMask Mask(std::stoul(Part, nullptr, 16)); + CPUMask Mask(benchmark::stoul(Part, nullptr, 16)); return static_cast(Mask.count()); }; size_t Pos; @@ -303,7 +330,7 @@ std::vector GetCacheSizesWindows() { if (!B.test(0)) continue; CInfo* Cache = &it->Cache; CPUInfo::CacheInfo C; - C.num_sharing = B.count(); + C.num_sharing = static_cast(B.count()); C.level = Cache->Level; C.size = Cache->Size; switch (Cache->Type) { @@ -354,6 +381,15 @@ int GetNumCPUs() { return sysinfo.dwNumberOfProcessors; // number of logical // processors in the current // group +#elif defined(BENCHMARK_OS_SOLARIS) + // Returns -1 in case of a failure. + int NumCPU = sysconf(_SC_NPROCESSORS_ONLN); + if (NumCPU < 0) { + fprintf(stderr, + "sysconf(_SC_NPROCESSORS_ONLN) failed with error: %s\n", + strerror(errno)); + } + return NumCPU; #else int NumCPUs = 0; int MaxID = -1; @@ -372,7 +408,7 @@ int GetNumCPUs() { if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) { NumCPUs++; if (!value.empty()) { - int CurID = std::stoi(value); + int CurID = benchmark::stoi(value); MaxID = std::max(CurID, MaxID); } } @@ -441,16 +477,16 @@ double GetCPUCyclesPerSecond() { std::string value; if (SplitIdx != std::string::npos) value = ln.substr(SplitIdx + 1); // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only - // accept postive values. Some environments (virtual machines) report zero, + // accept positive values. Some environments (virtual machines) report zero, // which would cause infinite looping in WallTime_Init. if (startsWithKey(ln, "cpu MHz")) { if (!value.empty()) { - double cycles_per_second = std::stod(value) * 1000000.0; + double cycles_per_second = benchmark::stod(value) * 1000000.0; if (cycles_per_second > 0) return cycles_per_second; } } else if (startsWithKey(ln, "bogomips")) { if (!value.empty()) { - bogo_clock = std::stod(value) * 1000000.0; + bogo_clock = benchmark::stod(value) * 1000000.0; if (bogo_clock < 0.0) bogo_clock = error_value; } } @@ -473,12 +509,17 @@ double GetCPUCyclesPerSecond() { constexpr auto* FreqStr = #if defined(BENCHMARK_OS_FREEBSD) || defined(BENCHMARK_OS_NETBSD) "machdep.tsc_freq"; +#elif defined BENCHMARK_OS_OPENBSD + "hw.cpuspeed"; #else "hw.cpufrequency"; #endif unsigned long long hz = 0; +#if defined BENCHMARK_OS_OPENBSD + if (GetSysctl(FreqStr, &hz)) return hz * 1000000; +#else if (GetSysctl(FreqStr, &hz)) return hz; - +#endif fprintf(stderr, "Unable to determine clock rate from sysctl: %s: %s\n", FreqStr, strerror(errno)); @@ -493,6 +534,35 @@ double GetCPUCyclesPerSecond() { "~MHz", nullptr, &data, &data_size))) return static_cast((int64_t)data * (int64_t)(1000 * 1000)); // was mhz +#elif defined (BENCHMARK_OS_SOLARIS) + kstat_ctl_t *kc = kstat_open(); + if (!kc) { + std::cerr << "failed to open /dev/kstat\n"; + return -1; + } + kstat_t *ksp = kstat_lookup(kc, (char*)"cpu_info", -1, (char*)"cpu_info0"); + if (!ksp) { + std::cerr << "failed to lookup in /dev/kstat\n"; + return -1; + } + if (kstat_read(kc, ksp, NULL) < 0) { + std::cerr << "failed to read from /dev/kstat\n"; + return -1; + } + kstat_named_t *knp = + (kstat_named_t*)kstat_data_lookup(ksp, (char*)"current_clock_Hz"); + if (!knp) { + std::cerr << "failed to lookup data in /dev/kstat\n"; + return -1; + } + if (knp->data_type != KSTAT_DATA_UINT64) { + std::cerr << "current_clock_Hz is of unexpected data type: " + << knp->data_type << "\n"; + return -1; + } + double clock_hz = knp->value.ui64; + kstat_close(kc); + return clock_hz; #endif // If we've fallen through, attempt to roughly estimate the CPU clock rate. const int estimate_time_ms = 1000; diff --git a/utils/google-benchmark/src/thread_manager.h b/utils/google-benchmark/src/thread_manager.h new file mode 100644 index 000000000..82b4d72b6 --- /dev/null +++ b/utils/google-benchmark/src/thread_manager.h @@ -0,0 +1,66 @@ +#ifndef BENCHMARK_THREAD_MANAGER_H +#define BENCHMARK_THREAD_MANAGER_H + +#include + +#include "benchmark/benchmark.h" +#include "mutex.h" + +namespace benchmark { +namespace internal { + +class ThreadManager { + public: + ThreadManager(int num_threads) + : alive_threads_(num_threads), start_stop_barrier_(num_threads) {} + + Mutex& GetBenchmarkMutex() const RETURN_CAPABILITY(benchmark_mutex_) { + return benchmark_mutex_; + } + + bool StartStopBarrier() EXCLUDES(end_cond_mutex_) { + return start_stop_barrier_.wait(); + } + + void NotifyThreadComplete() EXCLUDES(end_cond_mutex_) { + start_stop_barrier_.removeThread(); + if (--alive_threads_ == 0) { + MutexLock lock(end_cond_mutex_); + end_condition_.notify_all(); + } + } + + void WaitForAllThreads() EXCLUDES(end_cond_mutex_) { + MutexLock lock(end_cond_mutex_); + end_condition_.wait(lock.native_handle(), + [this]() { return alive_threads_ == 0; }); + } + + public: + struct Result { + int64_t iterations = 0; + 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_; + bool has_error_ = false; + UserCounters counters; + }; + GUARDED_BY(GetBenchmarkMutex()) Result results; + + private: + mutable Mutex benchmark_mutex_; + std::atomic alive_threads_; + Barrier start_stop_barrier_; + Mutex end_cond_mutex_; + Condition end_condition_; +}; + +} // namespace internal +} // namespace benchmark + +#endif // BENCHMARK_THREAD_MANAGER_H diff --git a/utils/google-benchmark/src/thread_timer.h b/utils/google-benchmark/src/thread_timer.h new file mode 100644 index 000000000..eaf108e01 --- /dev/null +++ b/utils/google-benchmark/src/thread_timer.h @@ -0,0 +1,69 @@ +#ifndef BENCHMARK_THREAD_TIMER_H +#define BENCHMARK_THREAD_TIMER_H + +#include "check.h" +#include "timers.h" + +namespace benchmark { +namespace internal { + +class ThreadTimer { + public: + ThreadTimer() = default; + + // Called by each thread + void StartTimer() { + running_ = true; + start_real_time_ = ChronoClockNow(); + start_cpu_time_ = ThreadCPUUsage(); + } + + // Called by each thread + void StopTimer() { + CHECK(running_); + running_ = false; + real_time_used_ += ChronoClockNow() - start_real_time_; + // Floating point error can result in the subtraction producing a negative + // time. Guard against that. + cpu_time_used_ += std::max(ThreadCPUUsage() - start_cpu_time_, 0); + } + + // Called by each thread + void SetIterationTime(double seconds) { manual_time_used_ += seconds; } + + bool running() const { return running_; } + + // REQUIRES: timer is not running + double real_time_used() { + CHECK(!running_); + return real_time_used_; + } + + // REQUIRES: timer is not running + double cpu_time_used() { + CHECK(!running_); + return cpu_time_used_; + } + + // REQUIRES: timer is not running + double manual_time_used() { + CHECK(!running_); + return manual_time_used_; + } + + private: + bool running_ = false; // Is the timer running + double start_real_time_ = 0; // If running_ + double start_cpu_time_ = 0; // If running_ + + // Accumulated time so far (does not contain current slice if running_) + double real_time_used_ = 0; + double cpu_time_used_ = 0; + // Manually set iteration time. User sets this with SetIterationTime(seconds). + double manual_time_used_ = 0; +}; + +} // namespace internal +} // namespace benchmark + +#endif // BENCHMARK_THREAD_TIMER_H diff --git a/utils/google-benchmark/src/timers.cc b/utils/google-benchmark/src/timers.cc index 817272d00..2010e2450 100644 --- a/utils/google-benchmark/src/timers.cc +++ b/utils/google-benchmark/src/timers.cc @@ -17,11 +17,14 @@ #ifdef BENCHMARK_OS_WINDOWS #include +#undef StrCat // Don't let StrCat in string_util.h be renamed to lstrcatA #include #include #else #include +#ifndef BENCHMARK_OS_FUCHSIA #include +#endif #include #include // this header must be included before 'sys/sysctl.h' to avoid compilation error on FreeBSD #include @@ -74,7 +77,7 @@ double MakeTime(FILETIME const& kernel_time, FILETIME const& user_time) { static_cast(user.QuadPart)) * 1e-7; } -#else +#elif !defined(BENCHMARK_OS_FUCHSIA) double MakeTime(struct rusage const& ru) { return (static_cast(ru.ru_utime.tv_sec) + static_cast(ru.ru_utime.tv_usec) * 1e-6 + @@ -162,6 +165,10 @@ double ThreadCPUUsage() { // RTEMS doesn't support CLOCK_THREAD_CPUTIME_ID. See // https://github.com/RTEMS/rtems/blob/master/cpukit/posix/src/clockgettime.c return ProcessCPUUsage(); +#elif defined(BENCHMARK_OS_SOLARIS) + struct rusage ru; + if (getrusage(RUSAGE_LWP, &ru) == 0) return MakeTime(ru); + DiagnoseAndExit("getrusage(RUSAGE_LWP, ...) failed"); #elif defined(CLOCK_THREAD_CPUTIME_ID) struct timespec ts; if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) return MakeTime(ts); @@ -186,7 +193,6 @@ std::string DateTimeString(bool local) { std::strftime(storage, sizeof(storage), "%x %X", ::localtime(&now)); #else std::tm timeinfo; - std::memset(&timeinfo, 0, sizeof(std::tm)); ::localtime_r(&now, &timeinfo); written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo); #endif @@ -195,7 +201,6 @@ std::string DateTimeString(bool local) { written = std::strftime(storage, sizeof(storage), "%x %X", ::gmtime(&now)); #else std::tm timeinfo; - std::memset(&timeinfo, 0, sizeof(std::tm)); ::gmtime_r(&now, &timeinfo); written = std::strftime(storage, sizeof(storage), "%F %T", &timeinfo); #endif diff --git a/utils/google-benchmark/test/BUILD b/utils/google-benchmark/test/BUILD new file mode 100644 index 000000000..3f174c486 --- /dev/null +++ b/utils/google-benchmark/test/BUILD @@ -0,0 +1,65 @@ +TEST_COPTS = [ + "-pedantic", + "-pedantic-errors", + "-std=c++11", + "-Wall", + "-Wextra", + "-Wshadow", +# "-Wshorten-64-to-32", + "-Wfloat-equal", + "-fstrict-aliasing", +] + +PER_SRC_COPTS = ({ + "cxx03_test.cc": ["-std=c++03"], + # Some of the issues with DoNotOptimize only occur when optimization is enabled + "donotoptimize_test.cc": ["-O3"], +}) + + +TEST_ARGS = ["--benchmark_min_time=0.01"] + +PER_SRC_TEST_ARGS = ({ + "user_counters_tabular_test.cc": ["--benchmark_counters_tabular=true"], +}) + +cc_library( + name = "output_test_helper", + testonly = 1, + srcs = ["output_test_helper.cc"], + hdrs = ["output_test.h"], + copts = TEST_COPTS, + deps = [ + "//:benchmark", + "//:benchmark_internal_headers", + ], +) + +[ + cc_test( + name = test_src[:-len(".cc")], + size = "small", + srcs = [test_src], + args = TEST_ARGS + PER_SRC_TEST_ARGS.get(test_src, []), + copts = TEST_COPTS + PER_SRC_COPTS.get(test_src, []), + deps = [ + ":output_test_helper", + "//:benchmark", + "//:benchmark_internal_headers", + "@com_google_googletest//:gtest", + ] + ( + ["@com_google_googletest//:gtest_main"] if (test_src[-len("gtest.cc"):] == "gtest.cc") else [] + ), + # FIXME: Add support for assembly tests to bazel. + # See Issue #556 + # https://github.com/google/benchmark/issues/556 + ) for test_src in glob(["*test.cc"], exclude = ["*_assembly_test.cc", "link_main_test.cc"]) +] + +cc_test( + name = "link_main_test", + size = "small", + srcs = ["link_main_test.cc"], + copts = TEST_COPTS, + deps = ["//:benchmark_main"], +) diff --git a/utils/google-benchmark/test/CMakeLists.txt b/utils/google-benchmark/test/CMakeLists.txt index efce3ba52..f49ca5148 100644 --- a/utils/google-benchmark/test/CMakeLists.txt +++ b/utils/google-benchmark/test/CMakeLists.txt @@ -22,6 +22,12 @@ if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" ) endforeach() endif() +check_cxx_compiler_flag(-O3 BENCHMARK_HAS_O3_FLAG) +set(BENCHMARK_O3_FLAG "") +if (BENCHMARK_HAS_O3_FLAG) + set(BENCHMARK_O3_FLAG "-O3") +endif() + # NOTE: These flags must be added after find_package(Threads REQUIRED) otherwise # they will break the configuration check. if (DEFINED BENCHMARK_CXX_LINKER_FLAGS) @@ -35,6 +41,10 @@ macro(compile_benchmark_test name) target_link_libraries(${name} benchmark ${CMAKE_THREAD_LIBS_INIT}) endmacro(compile_benchmark_test) +macro(compile_benchmark_test_with_main name) + add_executable(${name} "${name}.cc") + target_link_libraries(${name} benchmark_main) +endmacro(compile_benchmark_test_with_main) macro(compile_output_test name) add_executable(${name} "${name}.cc" output_test.h) @@ -53,14 +63,23 @@ macro(add_filter_test name filter expect) endmacro(add_filter_test) add_filter_test(filter_simple "Foo" 3) +add_filter_test(filter_simple_negative "-Foo" 2) add_filter_test(filter_suffix "BM_.*" 4) +add_filter_test(filter_suffix_negative "-BM_.*" 1) add_filter_test(filter_regex_all ".*" 5) +add_filter_test(filter_regex_all_negative "-.*" 0) add_filter_test(filter_regex_blank "" 5) +add_filter_test(filter_regex_blank_negative "-" 0) add_filter_test(filter_regex_none "monkey" 0) +add_filter_test(filter_regex_none_negative "-monkey" 5) add_filter_test(filter_regex_wildcard ".*Foo.*" 3) +add_filter_test(filter_regex_wildcard_negative "-.*Foo.*" 2) add_filter_test(filter_regex_begin "^BM_.*" 4) +add_filter_test(filter_regex_begin_negative "-^BM_.*" 1) add_filter_test(filter_regex_begin2 "^N" 1) +add_filter_test(filter_regex_begin2_negative "-^N" 4) add_filter_test(filter_regex_end ".*Ba$" 1) +add_filter_test(filter_regex_end_negative "-.*Ba$" 4) compile_benchmark_test(options_test) add_test(options_benchmarks options_test --benchmark_min_time=0.01) @@ -94,6 +113,9 @@ add_test(map_test map_test --benchmark_min_time=0.01) compile_benchmark_test(multiple_ranges_test) add_test(multiple_ranges_test multiple_ranges_test --benchmark_min_time=0.01) +compile_benchmark_test_with_main(link_main_test) +add_test(link_main_test link_main_test --benchmark_min_time=0.01) + compile_output_test(reporter_output_test) add_test(reporter_output_test reporter_output_test --benchmark_min_time=0.01) @@ -144,8 +166,11 @@ if (BENCHMARK_ENABLE_GTEST_TESTS) if (TARGET googletest) add_dependencies(${name} googletest) endif() + if (GTEST_INCLUDE_DIRS) + target_include_directories(${name} PRIVATE ${GTEST_INCLUDE_DIRS}) + endif() target_link_libraries(${name} benchmark - "${GTEST_BOTH_LIBRARIES}" ${CMAKE_THREAD_LIBS_INIT}) + ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) endmacro(compile_gtest) macro(add_gtest name) @@ -153,9 +178,30 @@ if (BENCHMARK_ENABLE_GTEST_TESTS) add_test(${name} ${name}) endmacro() - add_gtest(statistics_test) + add_gtest(benchmark_gtest) + add_gtest(statistics_gtest) + add_gtest(string_util_gtest) endif(BENCHMARK_ENABLE_GTEST_TESTS) +############################################################################### +# Assembly Unit Tests +############################################################################### + +if (BENCHMARK_ENABLE_ASSEMBLY_TESTS) + if (NOT LLVM_FILECHECK_EXE) + message(FATAL_ERROR "LLVM FileCheck is required when including this file") + endif() + include(AssemblyTests.cmake) + add_filecheck_test(donotoptimize_assembly_test) + add_filecheck_test(state_assembly_test) + add_filecheck_test(clobber_memory_assembly_test) +endif() + + + +############################################################################### +# Code Coverage Configuration +############################################################################### # Add the coverage command(s) if(CMAKE_BUILD_TYPE) diff --git a/utils/google-benchmark/test/basic_test.cc b/utils/google-benchmark/test/basic_test.cc index 3348781ce..d07fbc00b 100644 --- a/utils/google-benchmark/test/basic_test.cc +++ b/utils/google-benchmark/test/basic_test.cc @@ -99,13 +99,25 @@ BENCHMARK(BM_empty_stop_start)->ThreadPerCpu(); void BM_KeepRunning(benchmark::State& state) { size_t iter_count = 0; + assert(iter_count == state.iterations()); while (state.KeepRunning()) { ++iter_count; } - assert(iter_count == state.max_iterations); + assert(iter_count == state.iterations()); } BENCHMARK(BM_KeepRunning); +void BM_KeepRunningBatch(benchmark::State& state) { + // Choose a prime batch size to avoid evenly dividing max_iterations. + const size_t batch_size = 101; + size_t iter_count = 0; + while (state.KeepRunningBatch(batch_size)) { + iter_count += batch_size; + } + assert(state.iterations() == iter_count); +} +BENCHMARK(BM_KeepRunningBatch); + void BM_RangedFor(benchmark::State& state) { size_t iter_count = 0; for (auto _ : state) { @@ -115,4 +127,10 @@ void BM_RangedFor(benchmark::State& state) { } BENCHMARK(BM_RangedFor); +// Ensure that StateIterator provides all the necessary typedefs required to +// instantiate std::iterator_traits. +static_assert(std::is_same< + typename std::iterator_traits::value_type, + typename benchmark::State::StateIterator::value_type>::value, ""); + BENCHMARK_MAIN(); diff --git a/utils/google-benchmark/test/benchmark_gtest.cc b/utils/google-benchmark/test/benchmark_gtest.cc new file mode 100644 index 000000000..10683b433 --- /dev/null +++ b/utils/google-benchmark/test/benchmark_gtest.cc @@ -0,0 +1,33 @@ +#include + +#include "../src/benchmark_register.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace { + +TEST(AddRangeTest, Simple) { + std::vector dst; + AddRange(&dst, 1, 2, 2); + EXPECT_THAT(dst, testing::ElementsAre(1, 2)); +} + +TEST(AddRangeTest, Simple64) { + std::vector dst; + AddRange(&dst, static_cast(1), static_cast(2), 2); + EXPECT_THAT(dst, testing::ElementsAre(1, 2)); +} + +TEST(AddRangeTest, Advanced) { + std::vector dst; + AddRange(&dst, 5, 15, 2); + EXPECT_THAT(dst, testing::ElementsAre(5, 8, 15)); +} + +TEST(AddRangeTest, Advanced64) { + std::vector dst; + AddRange(&dst, static_cast(5), static_cast(15), 2); + EXPECT_THAT(dst, testing::ElementsAre(5, 8, 15)); +} + +} // end namespace diff --git a/utils/google-benchmark/test/benchmark_test.cc b/utils/google-benchmark/test/benchmark_test.cc index 78802c8da..3cd4f5565 100644 --- a/utils/google-benchmark/test/benchmark_test.cc +++ b/utils/google-benchmark/test/benchmark_test.cc @@ -40,8 +40,8 @@ double CalculatePi(int depth) { return (pi - 1.0) * 4; } -std::set ConstructRandomSet(int size) { - std::set s; +std::set ConstructRandomSet(int64_t size) { + std::set s; for (int i = 0; i < size; ++i) s.insert(s.end(), i); return s; } @@ -64,7 +64,7 @@ BENCHMARK(BM_Factorial)->UseRealTime(); static void BM_CalculatePiRange(benchmark::State& state) { double pi = 0.0; - for (auto _ : state) pi = CalculatePi(state.range(0)); + for (auto _ : state) pi = CalculatePi(static_cast(state.range(0))); std::stringstream ss; ss << pi; state.SetLabel(ss.str()); @@ -74,7 +74,7 @@ BENCHMARK_RANGE(BM_CalculatePiRange, 1, 1024 * 1024); static void BM_CalculatePi(benchmark::State& state) { static const int depth = 1024; for (auto _ : state) { - benchmark::DoNotOptimize(CalculatePi(depth)); + benchmark::DoNotOptimize(CalculatePi(static_cast(depth))); } } BENCHMARK(BM_CalculatePi)->Threads(8); @@ -82,7 +82,7 @@ BENCHMARK(BM_CalculatePi)->ThreadRange(1, 32); BENCHMARK(BM_CalculatePi)->ThreadPerCpu(); static void BM_SetInsert(benchmark::State& state) { - std::set data; + std::set data; for (auto _ : state) { state.PauseTiming(); data = ConstructRandomSet(state.range(0)); @@ -103,9 +103,9 @@ static void BM_Sequential(benchmark::State& state) { ValueType v = 42; for (auto _ : state) { Container c; - for (int i = state.range(0); --i;) c.push_back(v); + for (int64_t i = state.range(0); --i;) c.push_back(v); } - const size_t items_processed = state.iterations() * state.range(0); + const int64_t items_processed = state.iterations() * state.range(0); state.SetItemsProcessed(items_processed); state.SetBytesProcessed(items_processed * sizeof(v)); } @@ -118,8 +118,9 @@ BENCHMARK_TEMPLATE(BM_Sequential, std::vector, int)->Arg(512); #endif static void BM_StringCompare(benchmark::State& state) { - std::string s1(state.range(0), '-'); - std::string s2(state.range(0), '-'); + size_t len = static_cast(state.range(0)); + std::string s1(len, '-'); + std::string s2(len, '-'); for (auto _ : state) benchmark::DoNotOptimize(s1.compare(s2)); } BENCHMARK(BM_StringCompare)->Range(1, 1 << 20); @@ -154,13 +155,13 @@ static void BM_LongTest(benchmark::State& state) { BENCHMARK(BM_LongTest)->Range(1 << 16, 1 << 28); static void BM_ParallelMemset(benchmark::State& state) { - int size = state.range(0) / static_cast(sizeof(int)); - int thread_size = size / state.threads; + int64_t size = state.range(0) / static_cast(sizeof(int)); + int thread_size = static_cast(size) / state.threads; int from = thread_size * state.thread_index; int to = from + thread_size; if (state.thread_index == 0) { - test_vector = new std::vector(size); + test_vector = new std::vector(static_cast(size)); } for (auto _ : state) { @@ -178,8 +179,8 @@ static void BM_ParallelMemset(benchmark::State& state) { BENCHMARK(BM_ParallelMemset)->Arg(10 << 20)->ThreadRange(1, 4); static void BM_ManualTiming(benchmark::State& state) { - size_t slept_for = 0; - int microseconds = state.range(0); + int64_t slept_for = 0; + int64_t microseconds = state.range(0); std::chrono::duration sleep_duration{ static_cast(microseconds)}; diff --git a/utils/google-benchmark/test/clobber_memory_assembly_test.cc b/utils/google-benchmark/test/clobber_memory_assembly_test.cc new file mode 100644 index 000000000..f41911a39 --- /dev/null +++ b/utils/google-benchmark/test/clobber_memory_assembly_test.cc @@ -0,0 +1,64 @@ +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wreturn-type" +#endif + +extern "C" { + +extern int ExternInt; +extern int ExternInt2; +extern int ExternInt3; + +} + +// CHECK-LABEL: test_basic: +extern "C" void test_basic() { + int x; + benchmark::DoNotOptimize(&x); + x = 101; + benchmark::ClobberMemory(); + // CHECK: leaq [[DEST:[^,]+]], %rax + // CHECK: movl $101, [[DEST]] + // CHECK: ret +} + +// CHECK-LABEL: test_redundant_store: +extern "C" void test_redundant_store() { + ExternInt = 3; + benchmark::ClobberMemory(); + ExternInt = 51; + // CHECK-DAG: ExternInt + // CHECK-DAG: movl $3 + // CHECK: movl $51 +} + +// CHECK-LABEL: test_redundant_read: +extern "C" void test_redundant_read() { + int x; + benchmark::DoNotOptimize(&x); + x = ExternInt; + benchmark::ClobberMemory(); + x = ExternInt2; + // CHECK: leaq [[DEST:[^,]+]], %rax + // CHECK: ExternInt(%rip) + // CHECK: movl %eax, [[DEST]] + // CHECK-NOT: ExternInt2 + // CHECK: ret +} + +// CHECK-LABEL: test_redundant_read2: +extern "C" void test_redundant_read2() { + int x; + benchmark::DoNotOptimize(&x); + x = ExternInt; + benchmark::ClobberMemory(); + x = ExternInt2; + benchmark::ClobberMemory(); + // CHECK: leaq [[DEST:[^,]+]], %rax + // CHECK: ExternInt(%rip) + // CHECK: movl %eax, [[DEST]] + // CHECK: ExternInt2(%rip) + // CHECK: movl %eax, [[DEST]] + // CHECK: ret +} diff --git a/utils/google-benchmark/test/complexity_test.cc b/utils/google-benchmark/test/complexity_test.cc index 89dfa580e..5f9166089 100644 --- a/utils/google-benchmark/test/complexity_test.cc +++ b/utils/google-benchmark/test/complexity_test.cc @@ -55,7 +55,7 @@ void BM_Complexity_O1(benchmark::State& state) { } BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity(benchmark::o1); BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity(); -BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity([](int) { +BENCHMARK(BM_Complexity_O1)->Range(1, 1 << 18)->Complexity([](int64_t) { return 1.0; }); @@ -81,19 +81,19 @@ ADD_COMPLEXITY_CASES(big_o_1_test_name, rms_o_1_test_name, lambda_big_o_1); // --------------------------- Testing BigO O(N) --------------------------- // // ========================================================================= // -std::vector ConstructRandomVector(int size) { +std::vector ConstructRandomVector(int64_t size) { std::vector v; - v.reserve(size); + v.reserve(static_cast(size)); for (int i = 0; i < size; ++i) { - v.push_back(std::rand() % size); + v.push_back(static_cast(std::rand() % size)); } return v; } void BM_Complexity_O_N(benchmark::State& state) { auto v = ConstructRandomVector(state.range(0)); - const int item_not_in_vector = - state.range(0) * 2; // Test worst case scenario (item not in vector) + // Test worst case scenario (item not in vector) + const int64_t item_not_in_vector = state.range(0) * 2; for (auto _ : state) { benchmark::DoNotOptimize(std::find(v.begin(), v.end(), item_not_in_vector)); } @@ -106,7 +106,7 @@ BENCHMARK(BM_Complexity_O_N) BENCHMARK(BM_Complexity_O_N) ->RangeMultiplier(2) ->Range(1 << 10, 1 << 16) - ->Complexity([](int n) -> double { return n; }); + ->Complexity([](int64_t n) -> double { return static_cast(n); }); BENCHMARK(BM_Complexity_O_N) ->RangeMultiplier(2) ->Range(1 << 10, 1 << 16) @@ -134,6 +134,7 @@ static void BM_Complexity_O_N_log_N(benchmark::State& state) { } state.SetComplexityN(state.range(0)); } +static const double kLog2E = 1.44269504088896340736; BENCHMARK(BM_Complexity_O_N_log_N) ->RangeMultiplier(2) ->Range(1 << 10, 1 << 16) @@ -141,7 +142,7 @@ BENCHMARK(BM_Complexity_O_N_log_N) BENCHMARK(BM_Complexity_O_N_log_N) ->RangeMultiplier(2) ->Range(1 << 10, 1 << 16) - ->Complexity([](int n) { return n * log2(n); }); + ->Complexity([](int64_t n) { return kLog2E * n * log(static_cast(n)); }); BENCHMARK(BM_Complexity_O_N_log_N) ->RangeMultiplier(2) ->Range(1 << 10, 1 << 16) diff --git a/utils/google-benchmark/test/donotoptimize_assembly_test.cc b/utils/google-benchmark/test/donotoptimize_assembly_test.cc new file mode 100644 index 000000000..d4b0bab70 --- /dev/null +++ b/utils/google-benchmark/test/donotoptimize_assembly_test.cc @@ -0,0 +1,163 @@ +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wreturn-type" +#endif + +extern "C" { + +extern int ExternInt; +extern int ExternInt2; +extern int ExternInt3; + +inline int Add42(int x) { return x + 42; } + +struct NotTriviallyCopyable { + NotTriviallyCopyable(); + explicit NotTriviallyCopyable(int x) : value(x) {} + NotTriviallyCopyable(NotTriviallyCopyable const&); + int value; +}; + +struct Large { + int value; + int data[2]; +}; + +} +// CHECK-LABEL: test_with_rvalue: +extern "C" void test_with_rvalue() { + benchmark::DoNotOptimize(Add42(0)); + // CHECK: movl $42, %eax + // CHECK: ret +} + +// CHECK-LABEL: test_with_large_rvalue: +extern "C" void test_with_large_rvalue() { + benchmark::DoNotOptimize(Large{ExternInt, {ExternInt, ExternInt}}); + // CHECK: ExternInt(%rip) + // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]] + // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) + // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) + // CHECK: ret +} + +// CHECK-LABEL: test_with_non_trivial_rvalue: +extern "C" void test_with_non_trivial_rvalue() { + benchmark::DoNotOptimize(NotTriviallyCopyable(ExternInt)); + // CHECK: mov{{l|q}} ExternInt(%rip) + // CHECK: ret +} + +// CHECK-LABEL: test_with_lvalue: +extern "C" void test_with_lvalue() { + int x = 101; + benchmark::DoNotOptimize(x); + // CHECK-GNU: movl $101, %eax + // CHECK-CLANG: movl $101, -{{[0-9]+}}(%[[REG:[a-z]+]]) + // CHECK: ret +} + +// CHECK-LABEL: test_with_large_lvalue: +extern "C" void test_with_large_lvalue() { + Large L{ExternInt, {ExternInt, ExternInt}}; + benchmark::DoNotOptimize(L); + // CHECK: ExternInt(%rip) + // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]]) + // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) + // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) + // CHECK: ret +} + +// CHECK-LABEL: test_with_non_trivial_lvalue: +extern "C" void test_with_non_trivial_lvalue() { + NotTriviallyCopyable NTC(ExternInt); + benchmark::DoNotOptimize(NTC); + // CHECK: ExternInt(%rip) + // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]]) + // CHECK: ret +} + +// CHECK-LABEL: test_with_const_lvalue: +extern "C" void test_with_const_lvalue() { + const int x = 123; + benchmark::DoNotOptimize(x); + // CHECK: movl $123, %eax + // CHECK: ret +} + +// CHECK-LABEL: test_with_large_const_lvalue: +extern "C" void test_with_large_const_lvalue() { + const Large L{ExternInt, {ExternInt, ExternInt}}; + benchmark::DoNotOptimize(L); + // CHECK: ExternInt(%rip) + // CHECK: movl %eax, -{{[0-9]+}}(%[[REG:[a-z]+]]) + // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) + // CHECK: movl %eax, -{{[0-9]+}}(%[[REG]]) + // CHECK: ret +} + +// CHECK-LABEL: test_with_non_trivial_const_lvalue: +extern "C" void test_with_non_trivial_const_lvalue() { + const NotTriviallyCopyable Obj(ExternInt); + benchmark::DoNotOptimize(Obj); + // CHECK: mov{{q|l}} ExternInt(%rip) + // CHECK: ret +} + +// CHECK-LABEL: test_div_by_two: +extern "C" int test_div_by_two(int input) { + int divisor = 2; + benchmark::DoNotOptimize(divisor); + return input / divisor; + // CHECK: movl $2, [[DEST:.*]] + // CHECK: idivl [[DEST]] + // CHECK: ret +} + +// CHECK-LABEL: test_inc_integer: +extern "C" int test_inc_integer() { + int x = 0; + for (int i=0; i < 5; ++i) + benchmark::DoNotOptimize(++x); + // CHECK: movl $1, [[DEST:.*]] + // CHECK: {{(addl \$1,|incl)}} [[DEST]] + // CHECK: {{(addl \$1,|incl)}} [[DEST]] + // CHECK: {{(addl \$1,|incl)}} [[DEST]] + // CHECK: {{(addl \$1,|incl)}} [[DEST]] + // CHECK-CLANG: movl [[DEST]], %eax + // CHECK: ret + return x; +} + +// CHECK-LABEL: test_pointer_rvalue +extern "C" void test_pointer_rvalue() { + // CHECK: movl $42, [[DEST:.*]] + // CHECK: leaq [[DEST]], %rax + // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z]+]]) + // CHECK: ret + int x = 42; + benchmark::DoNotOptimize(&x); +} + +// CHECK-LABEL: test_pointer_const_lvalue: +extern "C" void test_pointer_const_lvalue() { + // CHECK: movl $42, [[DEST:.*]] + // CHECK: leaq [[DEST]], %rax + // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z]+]]) + // CHECK: ret + int x = 42; + int * const xp = &x; + benchmark::DoNotOptimize(xp); +} + +// CHECK-LABEL: test_pointer_lvalue: +extern "C" void test_pointer_lvalue() { + // CHECK: movl $42, [[DEST:.*]] + // CHECK: leaq [[DEST]], %rax + // CHECK-CLANG: movq %rax, -{{[0-9]+}}(%[[REG:[a-z+]+]]) + // CHECK: ret + int x = 42; + int *xp = &x; + benchmark::DoNotOptimize(xp); +} diff --git a/utils/google-benchmark/test/donotoptimize_test.cc b/utils/google-benchmark/test/donotoptimize_test.cc index a705654a2..2ce92d1c7 100644 --- a/utils/google-benchmark/test/donotoptimize_test.cc +++ b/utils/google-benchmark/test/donotoptimize_test.cc @@ -28,13 +28,13 @@ private: int main(int, char*[]) { // this test verifies compilation of DoNotOptimize() for some types - char buffer8[8]; + char buffer8[8] = ""; benchmark::DoNotOptimize(buffer8); - char buffer20[20]; + char buffer20[20] = ""; benchmark::DoNotOptimize(buffer20); - char buffer1024[1024]; + char buffer1024[1024] = ""; benchmark::DoNotOptimize(buffer1024); benchmark::DoNotOptimize(&buffer1024[0]); diff --git a/utils/google-benchmark/test/link_main_test.cc b/utils/google-benchmark/test/link_main_test.cc new file mode 100644 index 000000000..241ad5c39 --- /dev/null +++ b/utils/google-benchmark/test/link_main_test.cc @@ -0,0 +1,8 @@ +#include "benchmark/benchmark.h" + +void BM_empty(benchmark::State& state) { + for (auto _ : state) { + benchmark::DoNotOptimize(state.iterations()); + } +} +BENCHMARK(BM_empty); diff --git a/utils/google-benchmark/test/map_test.cc b/utils/google-benchmark/test/map_test.cc index 311d2d22b..dbf7982a3 100644 --- a/utils/google-benchmark/test/map_test.cc +++ b/utils/google-benchmark/test/map_test.cc @@ -8,7 +8,7 @@ namespace { std::map ConstructRandomMap(int size) { std::map m; for (int i = 0; i < size; ++i) { - m.insert(std::make_pair(rand() % size, rand() % size)); + m.insert(std::make_pair(std::rand() % size, std::rand() % size)); } return m; } @@ -17,14 +17,14 @@ std::map ConstructRandomMap(int size) { // Basic version. static void BM_MapLookup(benchmark::State& state) { - const int size = state.range(0); + const int size = static_cast(state.range(0)); std::map m; for (auto _ : state) { state.PauseTiming(); m = ConstructRandomMap(size); state.ResumeTiming(); for (int i = 0; i < size; ++i) { - benchmark::DoNotOptimize(m.find(rand() % size)); + benchmark::DoNotOptimize(m.find(std::rand() % size)); } } state.SetItemsProcessed(state.iterations() * size); @@ -35,7 +35,7 @@ BENCHMARK(BM_MapLookup)->Range(1 << 3, 1 << 12); class MapFixture : public ::benchmark::Fixture { public: void SetUp(const ::benchmark::State& st) { - m = ConstructRandomMap(st.range(0)); + m = ConstructRandomMap(static_cast(st.range(0))); } void TearDown(const ::benchmark::State&) { m.clear(); } @@ -44,10 +44,10 @@ class MapFixture : public ::benchmark::Fixture { }; BENCHMARK_DEFINE_F(MapFixture, Lookup)(benchmark::State& state) { - const int size = state.range(0); + const int size = static_cast(state.range(0)); for (auto _ : state) { for (int i = 0; i < size; ++i) { - benchmark::DoNotOptimize(m.find(rand() % size)); + benchmark::DoNotOptimize(m.find(std::rand() % size)); } } state.SetItemsProcessed(state.iterations() * size); diff --git a/utils/google-benchmark/test/multiple_ranges_test.cc b/utils/google-benchmark/test/multiple_ranges_test.cc index 0a82382f3..c64acabc2 100644 --- a/utils/google-benchmark/test/multiple_ranges_test.cc +++ b/utils/google-benchmark/test/multiple_ranges_test.cc @@ -1,7 +1,9 @@ #include "benchmark/benchmark.h" #include +#include #include +#include class MultipleRangesFixture : public ::benchmark::Fixture { public: @@ -27,25 +29,46 @@ class MultipleRangesFixture : public ::benchmark::Fixture { {7, 6, 3}}) {} void SetUp(const ::benchmark::State& state) { - std::vector ranges = {state.range(0), state.range(1), state.range(2)}; + std::vector ranges = {state.range(0), state.range(1), + state.range(2)}; assert(expectedValues.find(ranges) != expectedValues.end()); actualValues.insert(ranges); } + // NOTE: This is not TearDown as we want to check after _all_ runs are + // complete. virtual ~MultipleRangesFixture() { assert(actualValues.size() == expectedValues.size()); + if (actualValues.size() != expectedValues.size()) { + std::cout << "EXPECTED\n"; + for (auto v : expectedValues) { + std::cout << "{"; + for (int64_t iv : v) { + std::cout << iv << ", "; + } + std::cout << "}\n"; + } + std::cout << "ACTUAL\n"; + for (auto v : actualValues) { + std::cout << "{"; + for (int64_t iv : v) { + std::cout << iv << ", "; + } + std::cout << "}\n"; + } + } } - std::set> expectedValues; - std::set> actualValues; + std::set> expectedValues; + std::set> actualValues; }; BENCHMARK_DEFINE_F(MultipleRangesFixture, Empty)(benchmark::State& state) { for (auto _ : state) { - int product = state.range(0) * state.range(1) * state.range(2); - for (int x = 0; x < product; x++) { + int64_t product = state.range(0) * state.range(1) * state.range(2); + for (int64_t x = 0; x < product; x++) { benchmark::DoNotOptimize(x); } } diff --git a/utils/google-benchmark/test/output_test.h b/utils/google-benchmark/test/output_test.h index 897a13866..31a919991 100644 --- a/utils/google-benchmark/test/output_test.h +++ b/utils/google-benchmark/test/output_test.h @@ -2,13 +2,13 @@ #define TEST_OUTPUT_TEST_H #undef NDEBUG +#include #include #include +#include #include #include #include -#include -#include #include "../src/re.h" #include "benchmark/benchmark.h" @@ -73,26 +73,27 @@ void RunOutputTests(int argc, char* argv[]); // will be the subject of a call to checker_function // checker_function: should be of type ResultsCheckFn (see below) #define CHECK_BENCHMARK_RESULTS(bm_name_pattern, checker_function) \ - size_t CONCAT(dummy, __LINE__) = AddChecker(bm_name_pattern, checker_function) + size_t CONCAT(dummy, __LINE__) = AddChecker(bm_name_pattern, checker_function) struct Results; -typedef std::function< void(Results const&) > ResultsCheckFn; +typedef std::function ResultsCheckFn; size_t AddChecker(const char* bm_name_pattern, ResultsCheckFn fn); // Class holding the results of a benchmark. // It is passed in calls to checker functions. struct Results { - // the benchmark name std::string name; // the benchmark fields - std::map< std::string, std::string > values; + std::map values; Results(const std::string& n) : name(n) {} int NumThreads() const; + double NumIterations() const; + typedef enum { kCpuTime, kRealTime } BenchmarkTime; // get cpu_time or real_time in seconds @@ -102,18 +103,18 @@ struct Results { // it is better to use fuzzy float checks for this, as the float // ASCII formatting is lossy. double DurationRealTime() const { - return GetAs< double >("iterations") * GetTime(kRealTime); + return NumIterations() * GetTime(kRealTime); } // get the cpu_time duration of the benchmark in seconds double DurationCPUTime() const { - return GetAs< double >("iterations") * GetTime(kCpuTime); + return NumIterations() * GetTime(kCpuTime); } // get the string for a result by name, or nullptr if the name // is not found const std::string* Get(const char* entry_name) const { auto it = values.find(entry_name); - if(it == values.end()) return nullptr; + if (it == values.end()) return nullptr; return &it->second; } @@ -126,15 +127,15 @@ struct Results { // as a double, and only then converted to the asked type. template T GetCounterAs(const char* entry_name) const { - double dval = GetAs< double >(entry_name); - T tval = static_cast< T >(dval); + double dval = GetAs(entry_name); + T tval = static_cast(dval); return tval; } }; template T Results::GetAs(const char* entry_name) const { - auto *sv = Get(entry_name); + auto* sv = Get(entry_name); CHECK(sv != nullptr && !sv->empty()); std::stringstream ss; ss << *sv; @@ -148,6 +149,8 @@ T Results::GetAs(const char* entry_name) const { // Macros to help in result checking. Do not use them with arguments causing // side-effects. +// clang-format off + #define _CHECK_RESULT_VALUE(entry, getfn, var_type, var_name, relationship, value) \ CONCAT(CHECK_, relationship) \ (entry.getfn< var_type >(var_name), (value)) << "\n" \ @@ -188,6 +191,8 @@ T Results::GetAs(const char* entry_name) const { #define CHECK_FLOAT_COUNTER_VALUE(entry, var_name, relationship, value, eps_factor) \ _CHECK_FLOAT_RESULT_VALUE(entry, GetCounterAs, double, var_name, relationship, value, eps_factor) +// clang-format on + // ========================================================================= // // --------------------------- Misc Utilities ------------------------------ // // ========================================================================= // diff --git a/utils/google-benchmark/test/output_test_helper.cc b/utils/google-benchmark/test/output_test_helper.cc index 24746f6d2..394c4f5d1 100644 --- a/utils/google-benchmark/test/output_test_helper.cc +++ b/utils/google-benchmark/test/output_test_helper.cc @@ -1,13 +1,13 @@ +#include #include #include #include #include -#include +#include "../src/benchmark_api_internal.h" #include "../src/check.h" // NOTE: check.h is for internal use only! #include "../src/re.h" // NOTE: re.h is for internal use only #include "output_test.h" -#include "../src/benchmark_api_internal.h" // ========================================================================= // // ------------------------------ Internals -------------------------------- // @@ -33,6 +33,7 @@ TestCaseList& GetTestCaseList(TestCaseID ID) { 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 SubMap map = { {"%float", "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?"}, @@ -40,8 +41,8 @@ SubMap& GetSubstitutions() { {"%hrfloat", "[0-9]*[.]?[0-9]+([eE][-+][0-9]+)?[kMGTPEZYmunpfazy]?"}, {"%int", "[ ]*[0-9]+"}, {" %s ", "[ ]+"}, - {"%time", "[ ]*[0-9]{1,5} ns"}, - {"%console_report", "[ ]*[0-9]{1,5} ns [ ]*[0-9]{1,5} ns [ ]*[0-9]+"}, + {"%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]+"}, {"%csv_header", "name,iterations,real_time,cpu_time,time_unit,bytes_per_second," @@ -57,6 +58,7 @@ SubMap& GetSubstitutions() { "," + safe_dec_re + ",,,"}, {"%csv_label_report_begin", "[0-9]+," + safe_dec_re + "," + safe_dec_re + ",ns,,,"}, {"%csv_label_report_end", ",,"}}; + // clang-format on return map; } @@ -147,9 +149,9 @@ class TestReporter : public benchmark::BenchmarkReporter { } private: - std::vector reporters_; + std::vector reporters_; }; -} +} // namespace } // end namespace internal @@ -163,28 +165,25 @@ namespace internal { // It works by parsing the CSV output to read the results. class ResultsChecker { public: - - struct PatternAndFn : public TestCase { // reusing TestCase for its regexes + struct PatternAndFn : public TestCase { // reusing TestCase for its regexes PatternAndFn(const std::string& rx, ResultsCheckFn fn_) - : TestCase(rx), fn(fn_) {} + : TestCase(rx), fn(fn_) {} ResultsCheckFn fn; }; - std::vector< PatternAndFn > check_patterns; - std::vector< Results > results; - std::vector< std::string > field_names; + std::vector check_patterns; + std::vector results; + std::vector field_names; void Add(const std::string& entry_pattern, ResultsCheckFn fn); void CheckResults(std::stringstream& output); private: - void SetHeader_(const std::string& csv_header); void SetValues_(const std::string& entry_csv_line); - std::vector< std::string > SplitCsv_(const std::string& line); - + std::vector SplitCsv_(const std::string& line); }; // store the static ResultsChecker in a function to prevent initialization @@ -207,7 +206,7 @@ void ResultsChecker::CheckResults(std::stringstream& output) { // clear before calling tellg() output.clear(); // seek to zero only when needed - if(output.tellg() > start) output.seekg(start); + if (output.tellg() > start) output.seekg(start); // and just in case output.clear(); } @@ -218,18 +217,18 @@ void ResultsChecker::CheckResults(std::stringstream& output) { CHECK(output.good()); std::getline(output, line); if (on_first) { - SetHeader_(line); // this is important + SetHeader_(line); // this is important on_first = false; continue; } SetValues_(line); } // finally we can call the subscribed check functions - for(const auto& p : check_patterns) { + for (const auto& p : check_patterns) { VLOG(2) << "--------------------------------\n"; VLOG(2) << "checking for benchmarks matching " << p.regex_str << "...\n"; - for(const auto& r : results) { - if(!p.regex->Match(r.name)) { + for (const auto& r : results) { + if (!p.regex->Match(r.name)) { VLOG(2) << p.regex_str << " is not matched by " << r.name << "\n"; continue; } else { @@ -249,51 +248,50 @@ void ResultsChecker::SetHeader_(const std::string& csv_header) { // set the values for a benchmark void ResultsChecker::SetValues_(const std::string& entry_csv_line) { - if(entry_csv_line.empty()) return; // some lines are empty + if (entry_csv_line.empty()) return; // some lines are empty CHECK(!field_names.empty()); auto vals = SplitCsv_(entry_csv_line); CHECK_EQ(vals.size(), field_names.size()); - results.emplace_back(vals[0]); // vals[0] is the benchmark name - auto &entry = results.back(); + results.emplace_back(vals[0]); // vals[0] is the benchmark name + auto& entry = results.back(); for (size_t i = 1, e = vals.size(); i < e; ++i) { entry.values[field_names[i]] = vals[i]; } } // a quick'n'dirty csv splitter (eliminating quotes) -std::vector< std::string > ResultsChecker::SplitCsv_(const std::string& line) { - std::vector< std::string > out; - if(line.empty()) return out; - if(!field_names.empty()) out.reserve(field_names.size()); +std::vector ResultsChecker::SplitCsv_(const std::string& line) { + std::vector out; + if (line.empty()) return out; + if (!field_names.empty()) out.reserve(field_names.size()); size_t prev = 0, pos = line.find_first_of(','), curr = pos; - while(pos != line.npos) { + while (pos != line.npos) { CHECK(curr > 0); - if(line[prev] == '"') ++prev; - if(line[curr-1] == '"') --curr; - out.push_back(line.substr(prev, curr-prev)); + if (line[prev] == '"') ++prev; + if (line[curr - 1] == '"') --curr; + out.push_back(line.substr(prev, curr - prev)); prev = pos + 1; pos = line.find_first_of(',', pos + 1); curr = pos; } curr = line.size(); - if(line[prev] == '"') ++prev; - if(line[curr-1] == '"') --curr; - out.push_back(line.substr(prev, curr-prev)); + if (line[prev] == '"') ++prev; + if (line[curr - 1] == '"') --curr; + out.push_back(line.substr(prev, curr - prev)); return out; } } // end namespace internal -size_t AddChecker(const char* bm_name, ResultsCheckFn fn) -{ - auto &rc = internal::GetResultsChecker(); +size_t AddChecker(const char* bm_name, ResultsCheckFn fn) { + auto& rc = internal::GetResultsChecker(); rc.Add(bm_name, fn); return rc.results.size(); } int Results::NumThreads() const { auto pos = name.find("/threads:"); - if(pos == name.npos) return 1; + if (pos == name.npos) return 1; auto end = name.find('/', pos + 9); std::stringstream ss; ss << name.substr(pos + 9, end); @@ -303,19 +301,23 @@ int Results::NumThreads() const { return num; } +double Results::NumIterations() const { + return GetAs("iterations"); +} + double Results::GetTime(BenchmarkTime which) const { CHECK(which == kCpuTime || which == kRealTime); - const char *which_str = which == kCpuTime ? "cpu_time" : "real_time"; - double val = GetAs< double >(which_str); + const char* which_str = which == kCpuTime ? "cpu_time" : "real_time"; + double val = GetAs(which_str); auto unit = Get("time_unit"); CHECK(unit); - if(*unit == "ns") { + if (*unit == "ns") { return val * 1.e-9; - } else if(*unit == "us") { + } else if (*unit == "us") { return val * 1.e-6; - } else if(*unit == "ms") { + } else if (*unit == "ms") { return val * 1.e-3; - } else if(*unit == "s") { + } else if (*unit == "s") { return val; } else { CHECK(1 == 0) << "unknown time unit: " << *unit; @@ -333,7 +335,7 @@ TestCase::TestCase(std::string re, int rule) substituted_regex(internal::PerformSubstitutions(regex_str)), regex(std::make_shared()) { std::string err_str; - regex->Init(substituted_regex,& err_str); + regex->Init(substituted_regex, &err_str); CHECK(err_str.empty()) << "Could not construct regex \"" << substituted_regex << "\"" << "\n originally \"" << regex_str << "\"" @@ -367,7 +369,7 @@ int SetSubstitutions( void RunOutputTests(int argc, char* argv[]) { using internal::GetTestCaseList; benchmark::Initialize(&argc, argv); - auto options = benchmark::internal::GetOutputOptions(/*force_no_color*/true); + auto options = benchmark::internal::GetOutputOptions(/*force_no_color*/ true); benchmark::ConsoleReporter CR(options); benchmark::JSONReporter JR; benchmark::CSVReporter CSVR; @@ -416,7 +418,7 @@ void RunOutputTests(int argc, char* argv[]) { // now that we know the output is as expected, we can dispatch // the checks to subscribees. - auto &csv = TestCases[2]; + auto& csv = TestCases[2]; // would use == but gcc spits a warning CHECK(std::strcmp(csv.name, "CSVReporter") == 0); internal::GetResultsChecker().CheckResults(csv.out_stream); diff --git a/utils/google-benchmark/test/register_benchmark_test.cc b/utils/google-benchmark/test/register_benchmark_test.cc index 8ab2c2993..18de6d68e 100644 --- a/utils/google-benchmark/test/register_benchmark_test.cc +++ b/utils/google-benchmark/test/register_benchmark_test.cc @@ -29,6 +29,7 @@ struct TestCase { typedef benchmark::BenchmarkReporter::Run Run; void CheckRun(Run const& run) const { + // clang-format off CHECK(name == run.benchmark_name) << "expected " << name << " got " << run.benchmark_name; if (label) { @@ -37,6 +38,7 @@ struct TestCase { } else { CHECK(run.report_label == ""); } + // clang-format on } }; diff --git a/utils/google-benchmark/test/reporter_output_test.cc b/utils/google-benchmark/test/reporter_output_test.cc index 1620b3139..1662fcb8b 100644 --- a/utils/google-benchmark/test/reporter_output_test.cc +++ b/utils/google-benchmark/test/reporter_output_test.cc @@ -9,23 +9,25 @@ // ---------------------- Testing Prologue Output -------------------------- // // ========================================================================= // -ADD_CASES(TC_ConsoleOut, - {{"^[-]+$", MR_Next}, - {"^Benchmark %s Time %s CPU %s Iterations$", MR_Next}, - {"^[-]+$", MR_Next}}); +ADD_CASES(TC_ConsoleOut, {{"^[-]+$", MR_Next}, + {"^Benchmark %s Time %s CPU %s Iterations$", MR_Next}, + {"^[-]+$", MR_Next}}); static int AddContextCases() { AddCases(TC_ConsoleErr, { {"%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}, }); - AddCases(TC_JSONOut, {{"^\\{", MR_Default}, - {"\"context\":", MR_Next}, - {"\"date\": \"", MR_Next}, - {"\"num_cpus\": %int,$", MR_Next}, - {"\"mhz_per_cpu\": %float,$", MR_Next}, - {"\"cpu_scaling_enabled\": ", MR_Next}, - {"\"caches\": \\[$", MR_Next}}); + AddCases(TC_JSONOut, + {{"^\\{", MR_Default}, + {"\"context\":", MR_Next}, + {"\"date\": \"", 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; if (!Caches.empty()) { AddCases(TC_ConsoleErr, {{"CPU Caches:$", MR_Next}}); @@ -346,9 +348,12 @@ void BM_UserStats(benchmark::State& state) { for (auto _ : state) { } } +// clang-format off BENCHMARK(BM_UserStats) - ->Repetitions(3) - ->ComputeStatistics("", UserStatistics); + ->Repetitions(3) + ->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$"}, diff --git a/utils/google-benchmark/test/skip_with_error_test.cc b/utils/google-benchmark/test/skip_with_error_test.cc index 0c2f3481a..39785fb7f 100644 --- a/utils/google-benchmark/test/skip_with_error_test.cc +++ b/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) { @@ -70,6 +70,15 @@ void BM_error_before_running(benchmark::State& state) { BENCHMARK(BM_error_before_running); ADD_CASES("BM_error_before_running", {{"", true, "error message"}}); +void BM_error_before_running_batch(benchmark::State& state) { + state.SkipWithError("error message"); + while (state.KeepRunningBatch(17)) { + assert(false); + } +} +BENCHMARK(BM_error_before_running_batch); +ADD_CASES("BM_error_before_running_batch", {{"", true, "error message"}}); + void BM_error_before_running_range_for(benchmark::State& state) { state.SkipWithError("error message"); for (auto _ : state) { @@ -114,7 +123,7 @@ void BM_error_during_running_ranged_for(benchmark::State& state) { // Test the unfortunate but documented behavior that the ranged-for loop // doesn't automatically terminate when SkipWithError is set. assert(++It != End); - break; // Required behavior + break; // Required behavior } } } @@ -123,8 +132,6 @@ ADD_CASES("BM_error_during_running_ranged_for", {{"/1/iterations:5", true, "error message"}, {"/2/iterations:5", false, ""}}); - - void BM_error_after_running(benchmark::State& state) { for (auto _ : state) { benchmark::DoNotOptimize(state.iterations()); diff --git a/utils/google-benchmark/test/state_assembly_test.cc b/utils/google-benchmark/test/state_assembly_test.cc new file mode 100644 index 000000000..abe9a4ddb --- /dev/null +++ b/utils/google-benchmark/test/state_assembly_test.cc @@ -0,0 +1,68 @@ +#include + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wreturn-type" +#endif + +// clang-format off +extern "C" { + extern int ExternInt; + benchmark::State& GetState(); + void Fn(); +} +// clang-format on + +using benchmark::State; + +// CHECK-LABEL: test_for_auto_loop: +extern "C" int test_for_auto_loop() { + State& S = GetState(); + int x = 42; + // CHECK: [[CALL:call(q)*]] _ZN9benchmark5State16StartKeepRunningEv + // CHECK-NEXT: testq %rbx, %rbx + // CHECK-NEXT: je [[LOOP_END:.*]] + + for (auto _ : S) { + // CHECK: .L[[LOOP_HEAD:[a-zA-Z0-9_]+]]: + // CHECK-GNU-NEXT: subq $1, %rbx + // CHECK-CLANG-NEXT: {{(addq \$1,|incq)}} %rax + // CHECK-NEXT: jne .L[[LOOP_HEAD]] + benchmark::DoNotOptimize(x); + } + // CHECK: [[LOOP_END]]: + // CHECK: [[CALL]] _ZN9benchmark5State17FinishKeepRunningEv + + // CHECK: movl $101, %eax + // CHECK: ret + return 101; +} + +// CHECK-LABEL: test_while_loop: +extern "C" int test_while_loop() { + State& S = GetState(); + int x = 42; + + // CHECK: j{{(e|mp)}} .L[[LOOP_HEADER:[a-zA-Z0-9_]+]] + // CHECK-NEXT: .L[[LOOP_BODY:[a-zA-Z0-9_]+]]: + while (S.KeepRunning()) { + // CHECK-GNU-NEXT: subq $1, %[[IREG:[a-z]+]] + // CHECK-CLANG-NEXT: {{(addq \$-1,|decq)}} %[[IREG:[a-z]+]] + // CHECK: movq %[[IREG]], [[DEST:.*]] + benchmark::DoNotOptimize(x); + } + // CHECK-DAG: movq [[DEST]], %[[IREG]] + // CHECK-DAG: testq %[[IREG]], %[[IREG]] + // CHECK-DAG: jne .L[[LOOP_BODY]] + // CHECK-DAG: .L[[LOOP_HEADER]]: + + // CHECK: cmpb $0 + // CHECK-NEXT: jne .L[[LOOP_END:[a-zA-Z0-9_]+]] + // CHECK: [[CALL:call(q)*]] _ZN9benchmark5State16StartKeepRunningEv + + // CHECK: .L[[LOOP_END]]: + // CHECK: [[CALL]] _ZN9benchmark5State17FinishKeepRunningEv + + // CHECK: movl $101, %eax + // CHECK: ret + return 101; +} diff --git a/utils/google-benchmark/test/statistics_gtest.cc b/utils/google-benchmark/test/statistics_gtest.cc new file mode 100644 index 000000000..99e314920 --- /dev/null +++ b/utils/google-benchmark/test/statistics_gtest.cc @@ -0,0 +1,28 @@ +//===---------------------------------------------------------------------===// +// statistics_test - Unit tests for src/statistics.cc +//===---------------------------------------------------------------------===// + +#include "../src/statistics.h" +#include "gtest/gtest.h" + +namespace { +TEST(StatisticsTest, Mean) { + EXPECT_DOUBLE_EQ(benchmark::StatisticsMean({42, 42, 42, 42}), 42.0); + EXPECT_DOUBLE_EQ(benchmark::StatisticsMean({1, 2, 3, 4}), 2.5); + EXPECT_DOUBLE_EQ(benchmark::StatisticsMean({1, 2, 5, 10, 10, 14}), 7.0); +} + +TEST(StatisticsTest, Median) { + EXPECT_DOUBLE_EQ(benchmark::StatisticsMedian({42, 42, 42, 42}), 42.0); + EXPECT_DOUBLE_EQ(benchmark::StatisticsMedian({1, 2, 3, 4}), 2.5); + EXPECT_DOUBLE_EQ(benchmark::StatisticsMedian({1, 2, 5, 10, 10}), 5.0); +} + +TEST(StatisticsTest, StdDev) { + EXPECT_DOUBLE_EQ(benchmark::StatisticsStdDev({101, 101, 101, 101}), 0.0); + EXPECT_DOUBLE_EQ(benchmark::StatisticsStdDev({1, 2, 3}), 1.0); + EXPECT_FLOAT_EQ(benchmark::StatisticsStdDev({1.5, 2.4, 3.3, 4.2, 5.1}), + 1.42302495); +} + +} // end namespace diff --git a/utils/google-benchmark/test/statistics_test.cc b/utils/google-benchmark/test/statistics_test.cc deleted file mode 100644 index b4d6abbb5..000000000 --- a/utils/google-benchmark/test/statistics_test.cc +++ /dev/null @@ -1,61 +0,0 @@ -//===---------------------------------------------------------------------===// -// statistics_test - Unit tests for src/statistics.cc -//===---------------------------------------------------------------------===// - -#include "../src/statistics.h" -#include "gtest/gtest.h" - -namespace { -TEST(StatisticsTest, Mean) { - std::vector Inputs; - { - Inputs = {42, 42, 42, 42}; - double Res = benchmark::StatisticsMean(Inputs); - EXPECT_DOUBLE_EQ(Res, 42.0); - } - { - Inputs = {1, 2, 3, 4}; - double Res = benchmark::StatisticsMean(Inputs); - EXPECT_DOUBLE_EQ(Res, 2.5); - } - { - Inputs = {1, 2, 5, 10, 10, 14}; - double Res = benchmark::StatisticsMean(Inputs); - EXPECT_DOUBLE_EQ(Res, 7.0); - } -} - -TEST(StatisticsTest, Median) { - std::vector Inputs; - { - Inputs = {42, 42, 42, 42}; - double Res = benchmark::StatisticsMedian(Inputs); - EXPECT_DOUBLE_EQ(Res, 42.0); - } - { - Inputs = {1, 2, 3, 4}; - double Res = benchmark::StatisticsMedian(Inputs); - EXPECT_DOUBLE_EQ(Res, 2.5); - } - { - Inputs = {1, 2, 5, 10, 10}; - double Res = benchmark::StatisticsMedian(Inputs); - EXPECT_DOUBLE_EQ(Res, 5.0); - } -} - -TEST(StatisticsTest, StdDev) { - std::vector Inputs; - { - Inputs = {101, 101, 101, 101}; - double Res = benchmark::StatisticsStdDev(Inputs); - EXPECT_DOUBLE_EQ(Res, 0.0); - } - { - Inputs = {1, 2, 3}; - double Res = benchmark::StatisticsStdDev(Inputs); - EXPECT_DOUBLE_EQ(Res, 1.0); - } -} - -} // end namespace diff --git a/utils/google-benchmark/test/string_util_gtest.cc b/utils/google-benchmark/test/string_util_gtest.cc new file mode 100644 index 000000000..4c81734cf --- /dev/null +++ b/utils/google-benchmark/test/string_util_gtest.cc @@ -0,0 +1,146 @@ +//===---------------------------------------------------------------------===// +// statistics_test - Unit tests for src/statistics.cc +//===---------------------------------------------------------------------===// + +#include "../src/string_util.h" +#include "gtest/gtest.h" + +namespace { +TEST(StringUtilTest, stoul) { + { + size_t pos = 0; + EXPECT_EQ(0, benchmark::stoul("0", &pos)); + EXPECT_EQ(1, pos); + } + { + size_t pos = 0; + EXPECT_EQ(7, benchmark::stoul("7", &pos)); + EXPECT_EQ(1, pos); + } + { + size_t pos = 0; + EXPECT_EQ(135, benchmark::stoul("135", &pos)); + EXPECT_EQ(3, pos); + } +#if ULONG_MAX == 0xFFFFFFFFul + { + size_t pos = 0; + EXPECT_EQ(0xFFFFFFFFul, benchmark::stoul("4294967295", &pos)); + EXPECT_EQ(10, pos); + } +#elif ULONG_MAX == 0xFFFFFFFFFFFFFFFFul + { + size_t pos = 0; + EXPECT_EQ(0xFFFFFFFFFFFFFFFFul, benchmark::stoul("18446744073709551615", &pos)); + EXPECT_EQ(20, pos); + } +#endif + { + size_t pos = 0; + EXPECT_EQ(10, benchmark::stoul("1010", &pos, 2)); + EXPECT_EQ(4, pos); + } + { + size_t pos = 0; + EXPECT_EQ(520, benchmark::stoul("1010", &pos, 8)); + EXPECT_EQ(4, pos); + } + { + size_t pos = 0; + EXPECT_EQ(1010, benchmark::stoul("1010", &pos, 10)); + EXPECT_EQ(4, pos); + } + { + size_t pos = 0; + EXPECT_EQ(4112, benchmark::stoul("1010", &pos, 16)); + EXPECT_EQ(4, pos); + } + { + size_t pos = 0; + EXPECT_EQ(0xBEEF, benchmark::stoul("BEEF", &pos, 16)); + EXPECT_EQ(4, pos); + } + { + ASSERT_THROW(benchmark::stoul("this is a test"), std::invalid_argument); + } +} + +TEST(StringUtilTest, stoi) { + { + size_t pos = 0; + EXPECT_EQ(0, benchmark::stoi("0", &pos)); + EXPECT_EQ(1, pos); + } + { + size_t pos = 0; + EXPECT_EQ(-17, benchmark::stoi("-17", &pos)); + EXPECT_EQ(3, pos); + } + { + size_t pos = 0; + EXPECT_EQ(1357, benchmark::stoi("1357", &pos)); + EXPECT_EQ(4, pos); + } + { + size_t pos = 0; + EXPECT_EQ(10, benchmark::stoi("1010", &pos, 2)); + EXPECT_EQ(4, pos); + } + { + size_t pos = 0; + EXPECT_EQ(520, benchmark::stoi("1010", &pos, 8)); + EXPECT_EQ(4, pos); + } + { + size_t pos = 0; + EXPECT_EQ(1010, benchmark::stoi("1010", &pos, 10)); + EXPECT_EQ(4, pos); + } + { + size_t pos = 0; + EXPECT_EQ(4112, benchmark::stoi("1010", &pos, 16)); + EXPECT_EQ(4, pos); + } + { + size_t pos = 0; + EXPECT_EQ(0xBEEF, benchmark::stoi("BEEF", &pos, 16)); + EXPECT_EQ(4, pos); + } + { + ASSERT_THROW(benchmark::stoi("this is a test"), std::invalid_argument); + } +} + +TEST(StringUtilTest, stod) { + { + size_t pos = 0; + EXPECT_EQ(0.0, benchmark::stod("0", &pos)); + EXPECT_EQ(1, pos); + } + { + size_t pos = 0; + EXPECT_EQ(-84.0, benchmark::stod("-84", &pos)); + EXPECT_EQ(3, pos); + } + { + size_t pos = 0; + EXPECT_EQ(1234.0, benchmark::stod("1234", &pos)); + EXPECT_EQ(4, pos); + } + { + size_t pos = 0; + EXPECT_EQ(1.5, benchmark::stod("1.5", &pos)); + EXPECT_EQ(3, 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); + } + { + ASSERT_THROW(benchmark::stod("this is a test"), std::invalid_argument); + } +} + +} // end namespace diff --git a/utils/google-benchmark/test/templated_fixture_test.cc b/utils/google-benchmark/test/templated_fixture_test.cc index ec5b4c0cc..fe9865cc7 100644 --- a/utils/google-benchmark/test/templated_fixture_test.cc +++ b/utils/google-benchmark/test/templated_fixture_test.cc @@ -4,15 +4,15 @@ #include #include -template +template class MyFixture : public ::benchmark::Fixture { -public: + public: MyFixture() : data(0) {} T data; }; -BENCHMARK_TEMPLATE_F(MyFixture, Foo, int)(benchmark::State &st) { +BENCHMARK_TEMPLATE_F(MyFixture, Foo, int)(benchmark::State& st) { for (auto _ : st) { data += 1; } diff --git a/utils/google-benchmark/test/user_counters_tabular_test.cc b/utils/google-benchmark/test/user_counters_tabular_test.cc index 9b8a6132e..4f126b6d9 100644 --- a/utils/google-benchmark/test/user_counters_tabular_test.cc +++ b/utils/google-benchmark/test/user_counters_tabular_test.cc @@ -7,9 +7,11 @@ // @todo: this checks the full output at once; the rule for // CounterSet1 was failing because it was not matching "^[-]+$". // @todo: check that the counters are vertically aligned. -ADD_CASES(TC_ConsoleOut, { -// keeping these lines long improves readability, so: -// clang-format off +ADD_CASES( + TC_ConsoleOut, + { + // keeping these lines long improves readability, so: + // clang-format off {"^[-]+$", MR_Next}, {"^Benchmark %s Time %s CPU %s Iterations %s Bar %s Bat %s Baz %s Foo %s Frob %s Lob$", MR_Next}, {"^[-]+$", MR_Next}, @@ -44,8 +46,8 @@ ADD_CASES(TC_ConsoleOut, { {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$", MR_Next}, {"^BM_CounterSet2_Tabular/threads:%int %console_report [ ]*%hrfloat [ ]*%hrfloat [ ]*%hrfloat$"}, -// clang-format on -}); + // clang-format on + }); ADD_CASES(TC_CSVOut, {{"%csv_header," "\"Bar\",\"Bat\",\"Baz\",\"Foo\",\"Frob\",\"Lob\""}}); @@ -58,12 +60,12 @@ void BM_Counters_Tabular(benchmark::State& state) { } namespace bm = benchmark; state.counters.insert({ - {"Foo", { 1, bm::Counter::kAvgThreads}}, - {"Bar", { 2, bm::Counter::kAvgThreads}}, - {"Baz", { 4, bm::Counter::kAvgThreads}}, - {"Bat", { 8, bm::Counter::kAvgThreads}}, - {"Frob", {16, bm::Counter::kAvgThreads}}, - {"Lob", {32, bm::Counter::kAvgThreads}}, + {"Foo", {1, bm::Counter::kAvgThreads}}, + {"Bar", {2, bm::Counter::kAvgThreads}}, + {"Baz", {4, bm::Counter::kAvgThreads}}, + {"Bat", {8, bm::Counter::kAvgThreads}}, + {"Frob", {16, bm::Counter::kAvgThreads}}, + {"Lob", {32, bm::Counter::kAvgThreads}}, }); } BENCHMARK(BM_Counters_Tabular)->ThreadRange(1, 16); @@ -102,12 +104,12 @@ void BM_CounterRates_Tabular(benchmark::State& state) { } namespace bm = benchmark; state.counters.insert({ - {"Foo", { 1, bm::Counter::kAvgThreadsRate}}, - {"Bar", { 2, bm::Counter::kAvgThreadsRate}}, - {"Baz", { 4, bm::Counter::kAvgThreadsRate}}, - {"Bat", { 8, bm::Counter::kAvgThreadsRate}}, - {"Frob", {16, bm::Counter::kAvgThreadsRate}}, - {"Lob", {32, bm::Counter::kAvgThreadsRate}}, + {"Foo", {1, bm::Counter::kAvgThreadsRate}}, + {"Bar", {2, bm::Counter::kAvgThreadsRate}}, + {"Baz", {4, bm::Counter::kAvgThreadsRate}}, + {"Bat", {8, bm::Counter::kAvgThreadsRate}}, + {"Frob", {16, bm::Counter::kAvgThreadsRate}}, + {"Lob", {32, bm::Counter::kAvgThreadsRate}}, }); } BENCHMARK(BM_CounterRates_Tabular)->ThreadRange(1, 16); @@ -129,12 +131,12 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_CounterRates_Tabular/threads:%int\",%csv_report," // to CHECK_BENCHMARK_RESULTS() void CheckTabularRate(Results const& e) { double t = e.DurationCPUTime(); - CHECK_FLOAT_COUNTER_VALUE(e, "Foo", EQ, 1./t, 0.001); - CHECK_FLOAT_COUNTER_VALUE(e, "Bar", EQ, 2./t, 0.001); - CHECK_FLOAT_COUNTER_VALUE(e, "Baz", EQ, 4./t, 0.001); - CHECK_FLOAT_COUNTER_VALUE(e, "Bat", EQ, 8./t, 0.001); - CHECK_FLOAT_COUNTER_VALUE(e, "Frob", EQ, 16./t, 0.001); - CHECK_FLOAT_COUNTER_VALUE(e, "Lob", EQ, 32./t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "Foo", EQ, 1. / t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "Bar", EQ, 2. / t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "Baz", EQ, 4. / t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "Bat", EQ, 8. / t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "Frob", EQ, 16. / t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "Lob", EQ, 32. / t, 0.001); } CHECK_BENCHMARK_RESULTS("BM_CounterRates_Tabular/threads:%int", &CheckTabularRate); @@ -149,9 +151,9 @@ void BM_CounterSet0_Tabular(benchmark::State& state) { } namespace bm = benchmark; state.counters.insert({ - {"Foo", {10, bm::Counter::kAvgThreads}}, - {"Bar", {20, bm::Counter::kAvgThreads}}, - {"Baz", {40, bm::Counter::kAvgThreads}}, + {"Foo", {10, bm::Counter::kAvgThreads}}, + {"Bar", {20, bm::Counter::kAvgThreads}}, + {"Baz", {40, bm::Counter::kAvgThreads}}, }); } BENCHMARK(BM_CounterSet0_Tabular)->ThreadRange(1, 16); @@ -181,9 +183,9 @@ void BM_CounterSet1_Tabular(benchmark::State& state) { } namespace bm = benchmark; state.counters.insert({ - {"Foo", {15, bm::Counter::kAvgThreads}}, - {"Bar", {25, bm::Counter::kAvgThreads}}, - {"Baz", {45, bm::Counter::kAvgThreads}}, + {"Foo", {15, bm::Counter::kAvgThreads}}, + {"Bar", {25, bm::Counter::kAvgThreads}}, + {"Baz", {45, bm::Counter::kAvgThreads}}, }); } BENCHMARK(BM_CounterSet1_Tabular)->ThreadRange(1, 16); @@ -217,9 +219,9 @@ void BM_CounterSet2_Tabular(benchmark::State& state) { } namespace bm = benchmark; state.counters.insert({ - {"Foo", {10, bm::Counter::kAvgThreads}}, - {"Bat", {30, bm::Counter::kAvgThreads}}, - {"Baz", {40, bm::Counter::kAvgThreads}}, + {"Foo", {10, bm::Counter::kAvgThreads}}, + {"Bat", {30, bm::Counter::kAvgThreads}}, + {"Baz", {40, bm::Counter::kAvgThreads}}, }); } BENCHMARK(BM_CounterSet2_Tabular)->ThreadRange(1, 16); diff --git a/utils/google-benchmark/test/user_counters_test.cc b/utils/google-benchmark/test/user_counters_test.cc index 06aafb1fa..7f7ccb9f7 100644 --- a/utils/google-benchmark/test/user_counters_test.cc +++ b/utils/google-benchmark/test/user_counters_test.cc @@ -8,12 +8,16 @@ // ---------------------- Testing Prologue Output -------------------------- // // ========================================================================= // +// clang-format off + ADD_CASES(TC_ConsoleOut, {{"^[-]+$", MR_Next}, {"^Benchmark %s Time %s CPU %s Iterations UserCounters...$", MR_Next}, {"^[-]+$", MR_Next}}); ADD_CASES(TC_CSVOut, {{"%csv_header,\"bar\",\"foo\""}}); +// clang-format on + // ========================================================================= // // ------------------------- Simple Counters Output ------------------------ // // ========================================================================= // @@ -25,7 +29,8 @@ void BM_Counters_Simple(benchmark::State& state) { state.counters["bar"] = 2 * (double)state.iterations(); } BENCHMARK(BM_Counters_Simple); -ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_Simple %console_report bar=%hrfloat foo=%hrfloat$"}}); +ADD_CASES(TC_ConsoleOut, + {{"^BM_Counters_Simple %console_report bar=%hrfloat foo=%hrfloat$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Simple\",$"}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, @@ -38,10 +43,10 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_Simple\",%csv_report,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument // to CHECK_BENCHMARK_RESULTS() void CheckSimple(Results const& e) { - double its = e.GetAs< double >("iterations"); + double its = e.NumIterations(); CHECK_COUNTER_VALUE(e, int, "foo", EQ, 1); // check that the value of bar is within 0.1% of the expected value - CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2.*its, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. * its, 0.001); } CHECK_BENCHMARK_RESULTS("BM_Counters_Simple", &CheckSimple); @@ -49,7 +54,9 @@ CHECK_BENCHMARK_RESULTS("BM_Counters_Simple", &CheckSimple); // --------------------- Counters+Items+Bytes/s Output --------------------- // // ========================================================================= // -namespace { int num_calls1 = 0; } +namespace { +int num_calls1 = 0; +} void BM_Counters_WithBytesAndItemsPSec(benchmark::State& state) { for (auto _ : state) { } @@ -77,12 +84,12 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_WithBytesAndItemsPSec\"," // VS2013 does not allow this function to be passed as a lambda argument // to CHECK_BENCHMARK_RESULTS() void CheckBytesAndItemsPSec(Results const& e) { - double t = e.DurationCPUTime(); // this (and not real time) is the time used + double t = e.DurationCPUTime(); // this (and not real time) is the time used CHECK_COUNTER_VALUE(e, int, "foo", EQ, 1); CHECK_COUNTER_VALUE(e, int, "bar", EQ, num_calls1); // check that the values are within 0.1% of the expected values - CHECK_FLOAT_RESULT_VALUE(e, "bytes_per_second", EQ, 364./t, 0.001); - CHECK_FLOAT_RESULT_VALUE(e, "items_per_second", EQ, 150./t, 0.001); + CHECK_FLOAT_RESULT_VALUE(e, "bytes_per_second", EQ, 364. / t, 0.001); + CHECK_FLOAT_RESULT_VALUE(e, "items_per_second", EQ, 150. / t, 0.001); } CHECK_BENCHMARK_RESULTS("BM_Counters_WithBytesAndItemsPSec", &CheckBytesAndItemsPSec); @@ -99,7 +106,9 @@ void BM_Counters_Rate(benchmark::State& state) { state.counters["bar"] = bm::Counter{2, bm::Counter::kIsRate}; } BENCHMARK(BM_Counters_Rate); -ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_Rate %console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); +ADD_CASES( + TC_ConsoleOut, + {{"^BM_Counters_Rate %console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Rate\",$"}, {"\"iterations\": %int,$", MR_Next}, {"\"real_time\": %float,$", MR_Next}, @@ -112,10 +121,10 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_Rate\",%csv_report,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument // to CHECK_BENCHMARK_RESULTS() void CheckRate(Results const& e) { - double t = e.DurationCPUTime(); // this (and not real time) is the time used + double t = e.DurationCPUTime(); // this (and not real time) is the time used // check that the values are within 0.1% of the expected values - CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1./t, 0.001); - CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2./t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / t, 0.001); } CHECK_BENCHMARK_RESULTS("BM_Counters_Rate", &CheckRate); @@ -130,7 +139,8 @@ void BM_Counters_Threads(benchmark::State& state) { state.counters["bar"] = 2; } 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_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}, @@ -139,7 +149,9 @@ ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_Threads/threads:%int\",$"}, {"\"bar\": %float,$", MR_Next}, {"\"foo\": %float$", MR_Next}, {"}", MR_Next}}); -ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_Threads/threads:%int\",%csv_report,%float,%float$"}}); +ADD_CASES( + TC_CSVOut, + {{"^\"BM_Counters_Threads/threads:%int\",%csv_report,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument // to CHECK_BENCHMARK_RESULTS() void CheckThreads(Results const& e) { @@ -160,7 +172,8 @@ void BM_Counters_AvgThreads(benchmark::State& state) { state.counters["bar"] = bm::Counter{2, bm::Counter::kAvgThreads}; } 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_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}, @@ -169,7 +182,9 @@ ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_AvgThreads/threads:%int\",$"}, {"\"bar\": %float,$", MR_Next}, {"\"foo\": %float$", MR_Next}, {"}", MR_Next}}); -ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_AvgThreads/threads:%int\",%csv_report,%float,%float$"}}); +ADD_CASES( + TC_CSVOut, + {{"^\"BM_Counters_AvgThreads/threads:%int\",%csv_report,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument // to CHECK_BENCHMARK_RESULTS() void CheckAvgThreads(Results const& e) { @@ -191,8 +206,43 @@ void BM_Counters_AvgThreadsRate(benchmark::State& state) { state.counters["bar"] = bm::Counter{2, bm::Counter::kAvgThreadsRate}; } BENCHMARK(BM_Counters_AvgThreadsRate)->ThreadRange(1, 8); -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\",$"}, +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\",$"}, + {"\"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_AvgThreadsRate/" + "threads:%int\",%csv_report,%float,%float$"}}); +// VS2013 does not allow this function to be passed as a lambda argument +// to CHECK_BENCHMARK_RESULTS() +void CheckAvgThreadsRate(Results const& e) { + CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / e.DurationCPUTime(), 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / e.DurationCPUTime(), 0.001); +} +CHECK_BENCHMARK_RESULTS("BM_Counters_AvgThreadsRate/threads:%int", + &CheckAvgThreadsRate); + +// ========================================================================= // +// ------------------- IterationInvariant Counters Output ------------------ // +// ========================================================================= // + +void BM_Counters_IterationInvariant(benchmark::State& state) { + for (auto _ : state) { + } + namespace bm = benchmark; + state.counters["foo"] = bm::Counter{1, bm::Counter::kIsIterationInvariant}; + state.counters["bar"] = bm::Counter{2, bm::Counter::kIsIterationInvariant}; +} +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}, @@ -200,15 +250,128 @@ ADD_CASES(TC_JSONOut, {{"\"name\": \"BM_Counters_AvgThreadsRate/threads:%int\",$ {"\"bar\": %float,$", MR_Next}, {"\"foo\": %float$", MR_Next}, {"}", MR_Next}}); -ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_AvgThreadsRate/threads:%int\",%csv_report,%float,%float$"}}); +ADD_CASES(TC_CSVOut, + {{"^\"BM_Counters_IterationInvariant\",%csv_report,%float,%float$"}}); // VS2013 does not allow this function to be passed as a lambda argument // to CHECK_BENCHMARK_RESULTS() -void CheckAvgThreadsRate(Results const& e) { - CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1./e.DurationCPUTime(), 0.001); - CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2./e.DurationCPUTime(), 0.001); +void CheckIterationInvariant(Results const& e) { + double its = e.NumIterations(); + // check that the values are within 0.1% of the expected value + CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, its, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. * its, 0.001); } -CHECK_BENCHMARK_RESULTS("BM_Counters_AvgThreadsRate/threads:%int", - &CheckAvgThreadsRate); +CHECK_BENCHMARK_RESULTS("BM_Counters_IterationInvariant", + &CheckIterationInvariant); + +// ========================================================================= // +// ----------------- IterationInvariantRate Counters Output ---------------- // +// ========================================================================= // + +void BM_Counters_kIsIterationInvariantRate(benchmark::State& state) { + for (auto _ : state) { + } + namespace bm = benchmark; + state.counters["foo"] = + bm::Counter{1, bm::Counter::kIsIterationInvariantRate}; + state.counters["bar"] = + bm::Counter{2, bm::Counter::kIsRate | bm::Counter::kIsIterationInvariant}; +} +BENCHMARK(BM_Counters_kIsIterationInvariantRate); +ADD_CASES(TC_ConsoleOut, {{"^BM_Counters_kIsIterationInvariantRate " + "%console_report bar=%hrfloat/s foo=%hrfloat/s$"}}); +ADD_CASES(TC_JSONOut, + {{"\"name\": \"BM_Counters_kIsIterationInvariantRate\",$"}, + {"\"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_kIsIterationInvariantRate\",%csv_report," + "%float,%float$"}}); +// VS2013 does not allow this function to be passed as a lambda argument +// to CHECK_BENCHMARK_RESULTS() +void CheckIsIterationInvariantRate(Results const& e) { + double its = e.NumIterations(); + double t = e.DurationCPUTime(); // this (and not real time) is the time used + // check that the values are within 0.1% of the expected values + CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, its * 1. / t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, its * 2. / t, 0.001); +} +CHECK_BENCHMARK_RESULTS("BM_Counters_kIsIterationInvariantRate", + &CheckIsIterationInvariantRate); + +// ========================================================================= // +// ------------------- AvgIterations Counters Output ------------------ // +// ========================================================================= // + +void BM_Counters_AvgIterations(benchmark::State& state) { + for (auto _ : state) { + } + namespace bm = benchmark; + state.counters["foo"] = bm::Counter{1, bm::Counter::kAvgIterations}; + state.counters["bar"] = bm::Counter{2, bm::Counter::kAvgIterations}; +} +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_CSVOut, + {{"^\"BM_Counters_AvgIterations\",%csv_report,%float,%float$"}}); +// VS2013 does not allow this function to be passed as a lambda argument +// to CHECK_BENCHMARK_RESULTS() +void CheckAvgIterations(Results const& e) { + double its = e.NumIterations(); + // check that the values are within 0.1% of the expected value + CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / its, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / its, 0.001); +} +CHECK_BENCHMARK_RESULTS("BM_Counters_AvgIterations", &CheckAvgIterations); + +// ========================================================================= // +// ----------------- AvgIterationsRate Counters Output ---------------- // +// ========================================================================= // + +void BM_Counters_kAvgIterationsRate(benchmark::State& state) { + for (auto _ : state) { + } + namespace bm = benchmark; + state.counters["foo"] = bm::Counter{1, bm::Counter::kAvgIterationsRate}; + state.counters["bar"] = + bm::Counter{2, bm::Counter::kIsRate | bm::Counter::kAvgIterations}; +} +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_CSVOut, {{"^\"BM_Counters_kAvgIterationsRate\",%csv_report," + "%float,%float$"}}); +// VS2013 does not allow this function to be passed as a lambda argument +// to CHECK_BENCHMARK_RESULTS() +void CheckAvgIterationsRate(Results const& e) { + double its = e.NumIterations(); + double t = e.DurationCPUTime(); // this (and not real time) is the time used + // check that the values are within 0.1% of the expected values + CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / its / t, 0.001); + CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / its / t, 0.001); +} +CHECK_BENCHMARK_RESULTS("BM_Counters_kAvgIterationsRate", + &CheckAvgIterationsRate); // ========================================================================= // // --------------------------- TEST CASES END ------------------------------ // diff --git a/utils/google-benchmark/tools/compare.py b/utils/google-benchmark/tools/compare.py index c4a47e8d5..d27e24b34 100755 --- a/utils/google-benchmark/tools/compare.py +++ b/utils/google-benchmark/tools/compare.py @@ -35,6 +35,23 @@ def check_inputs(in1, in2, flags): def create_parser(): parser = ArgumentParser( description='versatile benchmark output compare tool') + + utest = parser.add_argument_group() + utest.add_argument( + '--no-utest', + dest='utest', + default=True, + action="store_false", + help="The tool can do a two-tailed Mann-Whitney U test with 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.\nWARNING: requires **LARGE** (no less than {}) number of repetitions to be meaningful!\nThe test is being done by default, if at least {} repetitions were done.\nThis option can disable the U Test.".format(report.UTEST_OPTIMAL_REPETITIONS, report.UTEST_MIN_REPETITIONS)) + alpha_default = 0.05 + utest.add_argument( + "--alpha", + dest='utest_alpha', + default=alpha_default, + type=float, + help=("significance level alpha. if the calculated p-value is below this value, then the result is said to be statistically significant and the null hypothesis is rejected.\n(default: %0.4f)") % + alpha_default) + subparsers = parser.add_subparsers( help='This tool has multiple modes of operation:', dest='mode') @@ -138,6 +155,9 @@ def main(): # Parse the command line flags parser = create_parser() args, unknown_args = parser.parse_known_args() + if args.mode is None: + parser.print_help() + exit(1) assert not unknown_args benchmark_options = args.benchmark_options @@ -175,6 +195,7 @@ def main(): else: # should never happen print("Unrecognized mode of operation: '%s'" % args.mode) + parser.print_help() exit(1) check_inputs(test_baseline, test_contender, benchmark_options) @@ -201,7 +222,8 @@ def main(): json2_orig, filter_contender, replacement) # Diff and output - output_lines = gbench.report.generate_difference_report(json1, json2) + output_lines = gbench.report.generate_difference_report( + json1, json2, args.utest, args.utest_alpha) print(description) for ln in output_lines: print(ln) @@ -218,12 +240,43 @@ class TestParser(unittest.TestCase): os.path.realpath(__file__)), 'gbench', 'Inputs') - self.testInput0 = os.path.join(testInputs, 'test_baseline_run1.json') - self.testInput1 = os.path.join(testInputs, 'test_baseline_run2.json') + self.testInput0 = os.path.join(testInputs, 'test1_run1.json') + self.testInput1 = os.path.join(testInputs, 'test1_run2.json') def test_benchmarks_basic(self): parsed = self.parser.parse_args( ['benchmarks', self.testInput0, self.testInput1]) + 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_without_utest(self): + parsed = self.parser.parse_args( + ['--no-utest', 'benchmarks', self.testInput0, self.testInput1]) + self.assertFalse(parsed.utest) + self.assertEqual(parsed.utest_alpha, 0.05) + 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.assertTrue(parsed.utest) + self.assertEqual(parsed.utest_alpha, 0.314) + 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_without_utest_with_utest_alpha(self): + parsed = self.parser.parse_args( + ['--no-utest', '--alpha=0.314', 'benchmarks', self.testInput0, self.testInput1]) + self.assertFalse(parsed.utest) + self.assertEqual(parsed.utest_alpha, 0.314) self.assertEqual(parsed.mode, 'benchmarks') self.assertEqual(parsed.test_baseline[0].name, self.testInput0) self.assertEqual(parsed.test_contender[0].name, self.testInput1) @@ -232,6 +285,7 @@ class TestParser(unittest.TestCase): def test_benchmarks_with_remainder(self): parsed = self.parser.parse_args( ['benchmarks', self.testInput0, self.testInput1, 'd']) + 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) @@ -240,6 +294,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.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) @@ -248,6 +303,7 @@ class TestParser(unittest.TestCase): def test_filters_basic(self): parsed = self.parser.parse_args( ['filters', self.testInput0, 'c', 'd']) + self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'filters') self.assertEqual(parsed.test[0].name, self.testInput0) self.assertEqual(parsed.filter_baseline[0], 'c') @@ -257,6 +313,7 @@ class TestParser(unittest.TestCase): def test_filters_with_remainder(self): parsed = self.parser.parse_args( ['filters', self.testInput0, 'c', 'd', 'e']) + self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'filters') self.assertEqual(parsed.test[0].name, self.testInput0) self.assertEqual(parsed.filter_baseline[0], 'c') @@ -266,6 +323,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.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'filters') self.assertEqual(parsed.test[0].name, self.testInput0) self.assertEqual(parsed.filter_baseline[0], 'c') @@ -275,6 +333,7 @@ class TestParser(unittest.TestCase): def test_benchmarksfiltered_basic(self): parsed = self.parser.parse_args( ['benchmarksfiltered', self.testInput0, 'c', self.testInput1, 'e']) + self.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'benchmarksfiltered') self.assertEqual(parsed.test_baseline[0].name, self.testInput0) self.assertEqual(parsed.filter_baseline[0], 'c') @@ -285,6 +344,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.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'benchmarksfiltered') self.assertEqual(parsed.test_baseline[0].name, self.testInput0) self.assertEqual(parsed.filter_baseline[0], 'c') @@ -295,6 +355,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.assertTrue(parsed.utest) self.assertEqual(parsed.mode, 'benchmarksfiltered') self.assertEqual(parsed.test_baseline[0].name, self.testInput0) self.assertEqual(parsed.filter_baseline[0], 'c') diff --git a/utils/google-benchmark/tools/gbench/Inputs/test3_run0.json b/utils/google-benchmark/tools/gbench/Inputs/test3_run0.json new file mode 100644 index 000000000..ca793f336 --- /dev/null +++ b/utils/google-benchmark/tools/gbench/Inputs/test3_run0.json @@ -0,0 +1,39 @@ +{ + "context": { + "date": "2016-08-02 17:44:46", + "num_cpus": 4, + "mhz_per_cpu": 4228, + "cpu_scaling_enabled": false, + "library_build_type": "release" + }, + "benchmarks": [ + { + "name": "BM_One", + "iterations": 1000, + "real_time": 10, + "cpu_time": 100, + "time_unit": "ns" + }, + { + "name": "BM_Two", + "iterations": 1000, + "real_time": 9, + "cpu_time": 90, + "time_unit": "ns" + }, + { + "name": "BM_Two", + "iterations": 1000, + "real_time": 8, + "cpu_time": 80, + "time_unit": "ns" + }, + { + "name": "short", + "iterations": 1000, + "real_time": 8, + "cpu_time": 80, + "time_unit": "ns" + } + ] +} diff --git a/utils/google-benchmark/tools/gbench/Inputs/test3_run1.json b/utils/google-benchmark/tools/gbench/Inputs/test3_run1.json new file mode 100644 index 000000000..e5cf50c74 --- /dev/null +++ b/utils/google-benchmark/tools/gbench/Inputs/test3_run1.json @@ -0,0 +1,39 @@ +{ + "context": { + "date": "2016-08-02 17:44:46", + "num_cpus": 4, + "mhz_per_cpu": 4228, + "cpu_scaling_enabled": false, + "library_build_type": "release" + }, + "benchmarks": [ + { + "name": "BM_One", + "iterations": 1000, + "real_time": 9, + "cpu_time": 110, + "time_unit": "ns" + }, + { + "name": "BM_Two", + "iterations": 1000, + "real_time": 10, + "cpu_time": 89, + "time_unit": "ns" + }, + { + "name": "BM_Two", + "iterations": 1000, + "real_time": 7, + "cpu_time": 70, + "time_unit": "ns" + }, + { + "name": "short", + "iterations": 1000, + "real_time": 8, + "cpu_time": 80, + "time_unit": "ns" + } + ] +} diff --git a/utils/google-benchmark/tools/gbench/report.py b/utils/google-benchmark/tools/gbench/report.py index 8d68fe96e..4d03a5476 100644 --- a/utils/google-benchmark/tools/gbench/report.py +++ b/utils/google-benchmark/tools/gbench/report.py @@ -4,6 +4,9 @@ import os import re import copy +from scipy.stats import mannwhitneyu + + class BenchmarkColor(object): def __init__(self, name, code): self.name = name @@ -16,11 +19,13 @@ class BenchmarkColor(object): def __format__(self, format): return self.code + # Benchmark Colors Enumeration BC_NONE = BenchmarkColor('NONE', '') BC_MAGENTA = BenchmarkColor('MAGENTA', '\033[95m') BC_CYAN = BenchmarkColor('CYAN', '\033[96m') BC_OKBLUE = BenchmarkColor('OKBLUE', '\033[94m') +BC_OKGREEN = BenchmarkColor('OKGREEN', '\033[32m') BC_HEADER = BenchmarkColor('HEADER', '\033[92m') BC_WARNING = BenchmarkColor('WARNING', '\033[93m') BC_WHITE = BenchmarkColor('WHITE', '\033[97m') @@ -29,6 +34,10 @@ BC_ENDC = BenchmarkColor('ENDC', '\033[0m') BC_BOLD = BenchmarkColor('BOLD', '\033[1m') BC_UNDERLINE = BenchmarkColor('UNDERLINE', '\033[4m') +UTEST_MIN_REPETITIONS = 2 +UTEST_OPTIMAL_REPETITIONS = 9 # Lowest reasonable number, More is better. + + def color_format(use_color, fmt_str, *args, **kwargs): """ Return the result of 'fmt_str.format(*args, **kwargs)' after transforming @@ -78,30 +87,90 @@ def filter_benchmark(json_orig, family, replacement=""): for be in json_orig['benchmarks']: if not regex.search(be['name']): continue - filteredbench = copy.deepcopy(be) # Do NOT modify the old name! + filteredbench = copy.deepcopy(be) # Do NOT modify the old name! filteredbench['name'] = regex.sub(replacement, filteredbench['name']) filtered['benchmarks'].append(filteredbench) return filtered -def generate_difference_report(json1, json2, use_color=True): +def generate_difference_report( + json1, + json2, + utest=False, + utest_alpha=0.05, + use_color=True): """ Calculate and report the difference between each test of two benchmarks runs specified as 'json1' and 'json2'. """ + assert utest is True or utest is False first_col_width = find_longest_name(json1['benchmarks']) + def find_test(name): for b in json2['benchmarks']: if b['name'] == name: return b return None - first_col_width = max(first_col_width, len('Benchmark')) + + utest_col_name = "_pvalue" + first_col_width = max( + first_col_width, + len('Benchmark')) + 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)] - gen = (bn for bn in json1['benchmarks'] if 'real_time' in bn and 'cpu_time' in bn) + 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 @@ -116,26 +185,44 @@ def generate_difference_report(json1, json2, use_color=True): return BC_WHITE else: return BC_CYAN - fmt_str = "{}{:<{}s}{endc}{}{:+16.4f}{endc}{}{:+16.4f}{endc}{:14.0f}{:14.0f}{endc}{:14.0f}{:14.0f}" - 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)] + + 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 TestReportDifference(unittest.TestCase): def load_results(self): import json - testInputs = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Inputs') + testInputs = os.path.join( + os.path.dirname( + os.path.realpath(__file__)), + 'Inputs') testOutput1 = os.path.join(testInputs, 'test1_run1.json') testOutput2 = os.path.join(testInputs, 'test1_run2.json') with open(testOutput1, 'r') as f: @@ -153,15 +240,20 @@ class TestReportDifference(unittest.TestCase): ['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_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'], ] json1, json2 = self.load_results() - output_lines_with_header = generate_difference_report(json1, json2, use_color=False) + output_lines_with_header = generate_difference_report( + json1, json2, 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)): @@ -173,7 +265,10 @@ class TestReportDifference(unittest.TestCase): class TestReportDifferenceBetweenFamilies(unittest.TestCase): def load_result(self): import json - testInputs = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Inputs') + testInputs = os.path.join( + os.path.dirname( + os.path.realpath(__file__)), + 'Inputs') testOutput = os.path.join(testInputs, 'test2_run.json') with open(testOutput, 'r') as f: json = json.load(f) @@ -189,9 +284,10 @@ class TestReportDifferenceBetweenFamilies(unittest.TestCase): json = self.load_result() json1 = filter_benchmark(json, "BM_Z.ro", ".") json2 = filter_benchmark(json, "BM_O.e", ".") - output_lines_with_header = generate_difference_report(json1, json2, use_color=False) + output_lines_with_header = generate_difference_report( + json1, json2, use_color=False) output_lines = output_lines_with_header[2:] - print "\n" + 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)): @@ -200,6 +296,54 @@ class TestReportDifferenceBetweenFamilies(unittest.TestCase): self.assertEqual(parts, expect_lines[i]) +class TestReportDifferenceWithUTest(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.2500', '+0.1125', '8', '10', '80', '89'], + ['BM_Two_pvalue', + '0.2207', + '0.6831', + 'U', + 'Test,', + 'Repetitions:', + '2.', + 'WARNING:', + 'Results', + 'unreliable!', + '9+', + 'repetitions', + 'recommended.'], + ['short', '+0.0000', '+0.0000', '8', '8', '80', '80'], + ] + json1, json2 = self.load_results() + output_lines_with_header = generate_difference_report( + json1, json2, True, 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]) + + if __name__ == '__main__': unittest.main() diff --git a/utils/google-benchmark/tools/strip_asm.py b/utils/google-benchmark/tools/strip_asm.py new file mode 100755 index 000000000..9030550b4 --- /dev/null +++ b/utils/google-benchmark/tools/strip_asm.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python + +""" +strip_asm.py - Cleanup ASM output for the specified file +""" + +from argparse import ArgumentParser +import sys +import os +import re + +def find_used_labels(asm): + found = set() + label_re = re.compile("\s*j[a-z]+\s+\.L([a-zA-Z0-9][a-zA-Z0-9_]*)") + for l in asm.splitlines(): + m = label_re.match(l) + if m: + found.add('.L%s' % m.group(1)) + return found + + +def normalize_labels(asm): + decls = set() + label_decl = re.compile("^[.]{0,1}L([a-zA-Z0-9][a-zA-Z0-9_]*)(?=:)") + for l in asm.splitlines(): + m = label_decl.match(l) + if m: + decls.add(m.group(0)) + if len(decls) == 0: + return asm + needs_dot = next(iter(decls))[0] != '.' + if not needs_dot: + return asm + for ld in decls: + asm = re.sub("(^|\s+)" + ld + "(?=:|\s)", '\\1.' + ld, asm) + return asm + + +def transform_labels(asm): + asm = normalize_labels(asm) + used_decls = find_used_labels(asm) + new_asm = '' + label_decl = re.compile("^\.L([a-zA-Z0-9][a-zA-Z0-9_]*)(?=:)") + for l in asm.splitlines(): + m = label_decl.match(l) + if not m or m.group(0) in used_decls: + new_asm += l + new_asm += '\n' + return new_asm + + +def is_identifier(tk): + if len(tk) == 0: + return False + first = tk[0] + if not first.isalpha() and first != '_': + return False + for i in range(1, len(tk)): + c = tk[i] + if not c.isalnum() and c != '_': + return False + return True + +def process_identifiers(l): + """ + process_identifiers - process all identifiers and modify them to have + consistent names across all platforms; specifically across ELF and MachO. + For example, MachO inserts an additional understore at the beginning of + names. This function removes that. + """ + parts = re.split(r'([a-zA-Z0-9_]+)', l) + new_line = '' + for tk in parts: + if is_identifier(tk): + if tk.startswith('__Z'): + tk = tk[1:] + elif tk.startswith('_') and len(tk) > 1 and \ + tk[1].isalpha() and tk[1] != 'Z': + tk = tk[1:] + new_line += tk + return new_line + + +def process_asm(asm): + """ + Strip the ASM of unwanted directives and lines + """ + new_contents = '' + asm = transform_labels(asm) + + # TODO: Add more things we want to remove + discard_regexes = [ + re.compile("\s+\..*$"), # directive + re.compile("\s*#(NO_APP|APP)$"), #inline ASM + re.compile("\s*#.*$"), # comment line + re.compile("\s*\.globa?l\s*([.a-zA-Z_][a-zA-Z0-9$_.]*)"), #global directive + re.compile("\s*\.(string|asciz|ascii|[1248]?byte|short|word|long|quad|value|zero)"), + ] + keep_regexes = [ + + ] + fn_label_def = re.compile("^[a-zA-Z_][a-zA-Z0-9_.]*:") + for l in asm.splitlines(): + # Remove Mach-O attribute + l = l.replace('@GOTPCREL', '') + add_line = True + for reg in discard_regexes: + if reg.match(l) is not None: + add_line = False + break + for reg in keep_regexes: + if reg.match(l) is not None: + add_line = True + break + if add_line: + if fn_label_def.match(l) and len(new_contents) != 0: + new_contents += '\n' + l = process_identifiers(l) + new_contents += l + new_contents += '\n' + return new_contents + +def main(): + parser = ArgumentParser( + description='generate a stripped assembly file') + parser.add_argument( + 'input', metavar='input', type=str, nargs=1, + help='An input assembly file') + parser.add_argument( + 'out', metavar='output', type=str, nargs=1, + help='The output file') + args, unknown_args = parser.parse_known_args() + input = args.input[0] + output = args.out[0] + if not os.path.isfile(input): + print(("ERROR: input file '%s' does not exist") % input) + sys.exit(1) + contents = None + with open(input, 'r') as f: + contents = f.read() + new_contents = process_asm(contents) + with open(output, 'w') as f: + f.write(new_contents) + + +if __name__ == '__main__': + main() + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 +# kate: tab-width: 4; replace-tabs on; indent-width 4; tab-indents: off; +# kate: indent-mode python; remove-trailing-spaces modified; -- GitLab From 97d4134fbcbbde4f118f4e400fefa1395b179861 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Tue, 10 Jul 2018 04:11:22 +0000 Subject: [PATCH 018/495] Add new string benchmarks git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336636 91177308-0d34-0410-b5e6-96231b3b80d8 --- benchmarks/string.bench.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/benchmarks/string.bench.cpp b/benchmarks/string.bench.cpp index 8324f3e99..8a09e738d 100644 --- a/benchmarks/string.bench.cpp +++ b/benchmarks/string.bench.cpp @@ -46,4 +46,25 @@ static void BM_StringFindMatch2(benchmark::State &state) { } 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()); + } + } +} +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()); + } +} +BENCHMARK(BM_StringCtorCStr)->Arg(1)->Arg(8)->Range(16, MAX_STRING_LEN / 4); + BENCHMARK_MAIN(); -- GitLab From 4a5f61abcbe801e717c0ee87db84afc5be3e4906 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 10 Jul 2018 13:21:03 +0000 Subject: [PATCH 019/495] [libc++] Declare operators with the proper visibility attribute Summary: Many operators in were _defined_ with the proper visibility attribute, but they were _declared_ without any. This is not a problem until we change the definition of _LIBCPP_INLINE_VISIBILITY to something that requires the declaration to be decorated. I also marked `strong_equality::operator weak_equality()` as `_LIBCPP_INLINE_VISIBILITY`, since it seems like it had been forgotten. This came up while trying to get rid of `__attribute__((__always_inline__))` in favor of `__attribute__((internal_linkage))`. Reviewers: EricWF, mclow.lists Subscribers: christof, dexonsmith, llvm-commits Differential Revision: https://reviews.llvm.org/D49104 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336665 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/compare | 110 ++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/include/compare b/include/compare index 17fc6ff05..07f88f09c 100644 --- a/include/compare +++ b/include/compare @@ -88,14 +88,14 @@ public: static const weak_equality equivalent; static const weak_equality nonequivalent; - friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept; - friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_equality __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, weak_equality __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(weak_equality __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_equality __v) noexcept; #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR - friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept; - friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr weak_equality operator<=>(weak_equality __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr weak_equality operator<=>(_CmpUnspecifiedParam, weak_equality __v) noexcept; #endif private: @@ -148,20 +148,20 @@ public: static const strong_equality nonequivalent; // conversion - constexpr operator weak_equality() const noexcept { + _LIBCPP_INLINE_VISIBILITY constexpr operator weak_equality() const noexcept { return __value_ == _EqResult::__zero ? weak_equality::equivalent : weak_equality::nonequivalent; } // comparisons - friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept; - friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_equality __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(strong_equality __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, strong_equality __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_equality __v) noexcept; #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR - friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept; - friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr strong_equality operator<=>(strong_equality __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr strong_equality operator<=>(_CmpUnspecifiedParam, strong_equality __v) noexcept; #endif private: _EqResult __value_; @@ -235,22 +235,22 @@ public: } // comparisons - friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept; - friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; - friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept; - friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; - friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept; - friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (partial_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (partial_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, partial_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, partial_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, partial_ordering __v) noexcept; #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR - friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(partial_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr partial_ordering operator<=>(_CmpUnspecifiedParam, partial_ordering __v) noexcept; #endif private: @@ -351,22 +351,22 @@ public: } // comparisons - friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept; - friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; - friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept; - friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; - friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept; - friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (weak_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (weak_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, weak_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, weak_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, weak_ordering __v) noexcept; #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR - friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(weak_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr weak_ordering operator<=>(_CmpUnspecifiedParam, weak_ordering __v) noexcept; #endif private: @@ -477,22 +477,22 @@ public: } // comparisons - friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept; - friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; - friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept; - friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; - friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept; - friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (strong_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (strong_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator==(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator!=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator< (_CmpUnspecifiedParam, strong_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator<=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator> (_CmpUnspecifiedParam, strong_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr bool operator>=(_CmpUnspecifiedParam, strong_ordering __v) noexcept; #ifndef _LIBCPP_HAS_NO_SPACESHIP_OPERATOR - friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept; - friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(strong_ordering __v, _CmpUnspecifiedParam) noexcept; + _LIBCPP_INLINE_VISIBILITY friend constexpr strong_ordering operator<=>(_CmpUnspecifiedParam, strong_ordering __v) noexcept; #endif private: -- GitLab From 7a0f119777f5c8880cf9743d604fd285765df399 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Tue, 10 Jul 2018 13:25:26 +0000 Subject: [PATCH 020/495] Remove BUILD file from google-benchmark git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336666 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/google-benchmark/test/BUILD | 65 ------------------------------- 1 file changed, 65 deletions(-) delete mode 100644 utils/google-benchmark/test/BUILD diff --git a/utils/google-benchmark/test/BUILD b/utils/google-benchmark/test/BUILD deleted file mode 100644 index 3f174c486..000000000 --- a/utils/google-benchmark/test/BUILD +++ /dev/null @@ -1,65 +0,0 @@ -TEST_COPTS = [ - "-pedantic", - "-pedantic-errors", - "-std=c++11", - "-Wall", - "-Wextra", - "-Wshadow", -# "-Wshorten-64-to-32", - "-Wfloat-equal", - "-fstrict-aliasing", -] - -PER_SRC_COPTS = ({ - "cxx03_test.cc": ["-std=c++03"], - # Some of the issues with DoNotOptimize only occur when optimization is enabled - "donotoptimize_test.cc": ["-O3"], -}) - - -TEST_ARGS = ["--benchmark_min_time=0.01"] - -PER_SRC_TEST_ARGS = ({ - "user_counters_tabular_test.cc": ["--benchmark_counters_tabular=true"], -}) - -cc_library( - name = "output_test_helper", - testonly = 1, - srcs = ["output_test_helper.cc"], - hdrs = ["output_test.h"], - copts = TEST_COPTS, - deps = [ - "//:benchmark", - "//:benchmark_internal_headers", - ], -) - -[ - cc_test( - name = test_src[:-len(".cc")], - size = "small", - srcs = [test_src], - args = TEST_ARGS + PER_SRC_TEST_ARGS.get(test_src, []), - copts = TEST_COPTS + PER_SRC_COPTS.get(test_src, []), - deps = [ - ":output_test_helper", - "//:benchmark", - "//:benchmark_internal_headers", - "@com_google_googletest//:gtest", - ] + ( - ["@com_google_googletest//:gtest_main"] if (test_src[-len("gtest.cc"):] == "gtest.cc") else [] - ), - # FIXME: Add support for assembly tests to bazel. - # See Issue #556 - # https://github.com/google/benchmark/issues/556 - ) for test_src in glob(["*test.cc"], exclude = ["*_assembly_test.cc", "link_main_test.cc"]) -] - -cc_test( - name = "link_main_test", - size = "small", - srcs = ["link_main_test.cc"], - copts = TEST_COPTS, - deps = ["//:benchmark_main"], -) -- GitLab From bb716549f1a0d445616cf1d2619623a599d12bea Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 10 Jul 2018 17:38:30 +0000 Subject: [PATCH 021/495] [libc++] Declare noop_coroutine() with _LIBCPP_INLINE_VISIBILITY Summary: It was defined with the right visibility, but declared without any visibility. This function was left out of a prior revision that did the same to several functions in (r336665) because the compiler I used didn't support coroutines. This reinforces the need for automated checks -- there might still be several cases of this throughout the library. Reviewers: EricWF Subscribers: modocache, christof, dexonsmith, llvm-commits Differential Revision: https://reviews.llvm.org/D49145 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336709 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/experimental/coroutine | 1 + 1 file changed, 1 insertion(+) diff --git a/include/experimental/coroutine b/include/experimental/coroutine index 32d55fa57..1eb224a53 100644 --- a/include/experimental/coroutine +++ b/include/experimental/coroutine @@ -283,6 +283,7 @@ public: _LIBCPP_CONSTEXPR_AFTER_CXX17 void destroy() const _NOEXCEPT {} private: + _LIBCPP_INLINE_VISIBILITY friend coroutine_handle noop_coroutine() _NOEXCEPT; _LIBCPP_INLINE_VISIBILITY coroutine_handle() _NOEXCEPT { -- GitLab From f51cf5e75e023fe238348cb87e2431b5a0168008 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 10 Jul 2018 19:13:33 +0000 Subject: [PATCH 022/495] [CMake] Set per-runtime library directory suffix in runtimes build Do not use LLVM_RUNTIMES_LIBDIR_SUFFIX variable which is an internal variable used by the runtimes build from individual runtimes, instead set per-runtime librarhy directory suffix variable which is necessary for the sanitized runtimes build to install libraries into correct location. Differential Revision: https://reviews.llvm.org/D49121 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336713 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6b8babad..6521ebbe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -387,7 +387,7 @@ string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) set(DEFAULT_INSTALL_PREFIX lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/) set(DEFAULT_INSTALL_HEADER_PREFIX lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}/) - set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/lib${LLVM_RUNTIMES_LIBDIR_SUFFIX}) + set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}/${LLVM_DEFAULT_TARGET_TRIPLE}/lib${LIBCXX_LIBDIR_SUFFIX}) set(LIBCXX_HEADER_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}) elseif(LLVM_LIBRARY_OUTPUT_INTDIR) set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) -- GitLab From 839b1a6ebd38757bd4a6d0a9567fbc748abf64f6 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 11 Jul 2018 21:20:42 +0000 Subject: [PATCH 023/495] Fix a test #ifdef that was reversed. NFC to the library. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336855 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/std/strings/string.view/string.view.cons/assign.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/std/strings/string.view/string.view.cons/assign.pass.cpp b/test/std/strings/string.view/string.view.cons/assign.pass.cpp index b7348ea22..f31bc6d5b 100644 --- a/test/std/strings/string.view/string.view.cons/assign.pass.cpp +++ b/test/std/strings/string.view/string.view.cons/assign.pass.cpp @@ -41,7 +41,7 @@ int main () { #if TEST_STD_VER > 11 static_assert( test ({ "abc", 3}), ""); -#ifdef _LIBCPP_HAS_NO_UNICODE_CHARS +#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS static_assert( test ({u"abc", 3}), ""); static_assert( test ({U"abc", 3}), ""); #endif -- GitLab From 88709a3f4ede9142bee41f3adadaa499bae46854 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 11 Jul 2018 21:22:13 +0000 Subject: [PATCH 024/495] Same reversed ifdef happened twice. Test fix only, NFC to the library. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336856 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/std/strings/string.view/string.view.cons/assign.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/std/strings/string.view/string.view.cons/assign.pass.cpp b/test/std/strings/string.view/string.view.cons/assign.pass.cpp index f31bc6d5b..478bec7e5 100644 --- a/test/std/strings/string.view/string.view.cons/assign.pass.cpp +++ b/test/std/strings/string.view/string.view.cons/assign.pass.cpp @@ -33,7 +33,7 @@ bool test (T sv0) int main () { assert( test ( "1234")); -#ifdef _LIBCPP_HAS_NO_UNICODE_CHARS +#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS assert( test (u"1234")); assert( test (U"1234")); #endif -- GitLab From 54238057d6a12f3bb10429374d2c3137ef8983fd Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 11 Jul 2018 23:14:33 +0000 Subject: [PATCH 025/495] [libc++] Take 2: Replace uses of _LIBCPP_ALWAYS_INLINE by _LIBCPP_INLINE_VISIBILITY Summary: We never actually mean to always inline a function -- all the uses of the macro I could find are actually attempts to control the visibility of symbols. This is better described by _LIBCPP_INLINE_VISIBILITY, which is actually always defined the same. This change is orthogonal to the decision of what we're actually going to do with _LIBCPP_INLINE_VISIBILITY -- it just simplifies things by having one canonical way of doing things. Note that this commit had originally been applied in r336369 and then reverted in r336382 because of unforeseen problems. Both of these problems have now been fixed. Reviewers: EricWF, mclow.lists Subscribers: christof, dexonsmith, erikvanderpoel Differential Revision: https://reviews.llvm.org/D48892 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336866 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/DesignDocs/VisibilityMacros.rst | 8 +- include/__bsd_locale_fallbacks.h | 22 +-- include/__config | 16 +- include/__locale | 168 ++++++++--------- include/__nullptr | 16 +- include/any | 6 +- include/cmath | 12 +- include/codecvt | 36 ++-- include/exception | 4 +- include/experimental/dynarray | 2 +- include/experimental/filesystem | 12 +- include/functional | 2 +- include/future | 2 +- include/initializer_list | 10 +- include/ios | 34 ++-- include/locale | 176 +++++++++--------- include/math.h | 24 +-- include/memory | 6 +- include/new | 2 +- include/ostream | 4 +- include/regex | 2 +- include/stdexcept | 16 +- include/streambuf | 14 +- include/support/android/locale_bionic.h | 12 +- include/support/xlocale/__posix_l_fallback.h | 78 ++++---- include/support/xlocale/__strtonum_fallback.h | 24 +-- include/system_error | 48 ++--- include/typeinfo | 2 +- include/vector | 2 +- src/support/win32/thread_win32.cpp | 4 +- 30 files changed, 377 insertions(+), 387 deletions(-) diff --git a/docs/DesignDocs/VisibilityMacros.rst b/docs/DesignDocs/VisibilityMacros.rst index 993ce2cca..69a09974a 100644 --- a/docs/DesignDocs/VisibilityMacros.rst +++ b/docs/DesignDocs/VisibilityMacros.rst @@ -41,10 +41,10 @@ Visibility Macros library and has an empty definition otherwise. **_LIBCPP_INLINE_VISIBILITY** - Mark a function as hidden and force inlining whenever possible. - -**_LIBCPP_ALWAYS_INLINE** - A synonym for `_LIBCPP_INLINE_VISIBILITY` + Mark a function as not being part of the ABI of any final linked image that + uses it, and also as being internal to each TU that uses that function. In + other words, the address of a function marked with this attribute is not + guaranteed to be the same across translation units. **_LIBCPP_TYPE_VIS** Mark a type's typeinfo, vtable and members as having default visibility. diff --git a/include/__bsd_locale_fallbacks.h b/include/__bsd_locale_fallbacks.h index 5e9e09483..3097b0141 100644 --- a/include/__bsd_locale_fallbacks.h +++ b/include/__bsd_locale_fallbacks.h @@ -24,28 +24,28 @@ _LIBCPP_BEGIN_NAMESPACE_STD -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l) { __libcpp_locale_guard __current(__l); return MB_CUR_MAX; } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY wint_t __libcpp_btowc_l(int __c, locale_t __l) { __libcpp_locale_guard __current(__l); return btowc(__c); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY int __libcpp_wctob_l(wint_t __c, locale_t __l) { __libcpp_locale_guard __current(__l); return wctob(__c); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc, size_t __len, mbstate_t *__ps, locale_t __l) { @@ -53,14 +53,14 @@ size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc, return wcsnrtombs(__dest, __src, __nwc, __len, __ps); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l) { __libcpp_locale_guard __current(__l); return wcrtomb(__s, __wc, __ps); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms, size_t __len, mbstate_t *__ps, locale_t __l) { @@ -68,7 +68,7 @@ size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms, return mbsnrtowcs(__dest, __src, __nms, __len, __ps); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) { @@ -76,28 +76,28 @@ size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n, return mbrtowc(__pwc, __s, __n, __ps); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY int __libcpp_mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l) { __libcpp_locale_guard __current(__l); return mbtowc(__pwc, __pmb, __max); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l) { __libcpp_locale_guard __current(__l); return mbrlen(__s, __n, __ps); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY lconv *__libcpp_localeconv_l(locale_t __l) { __libcpp_locale_guard __current(__l); return localeconv(); } -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len, mbstate_t *__ps, locale_t __l) { diff --git a/include/__config b/include/__config index 52c7142ff..233c2b3ab 100644 --- a/include/__config +++ b/include/__config @@ -672,11 +672,9 @@ namespace std { #if defined(_LIBCPP_COMPILER_MSVC) # define _LIBCPP_INLINE_VISIBILITY __forceinline -# define _LIBCPP_ALWAYS_INLINE __forceinline # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __forceinline #else # define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__always_inline__)) -# define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__ ((__always_inline__)) #endif @@ -771,14 +769,6 @@ namespace std { # endif #endif -#ifndef _LIBCPP_ALWAYS_INLINE -# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) -# define _LIBCPP_ALWAYS_INLINE __attribute__ ((__visibility__("hidden"), __always_inline__)) -# else -# define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) -# endif -#endif - #ifndef _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__((__visibility__("default"), __always_inline__)) @@ -889,9 +879,9 @@ template struct __static_assert_check {}; # define _LIBCPP_DECLARE_STRONG_ENUM(x) struct _LIBCPP_TYPE_VIS x { enum __lx # define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \ __lx __v_; \ - _LIBCPP_ALWAYS_INLINE x(__lx __v) : __v_(__v) {} \ - _LIBCPP_ALWAYS_INLINE explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ - _LIBCPP_ALWAYS_INLINE operator int() const {return __v_;} \ + _LIBCPP_INLINE_VISIBILITY x(__lx __v) : __v_(__v) {} \ + _LIBCPP_INLINE_VISIBILITY explicit x(int __v) : __v_(static_cast<__lx>(__v)) {} \ + _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;} \ }; #else // _LIBCPP_HAS_NO_STRONG_ENUMS # define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_ENUM_VIS x diff --git a/include/__locale b/include/__locale index c293b81fb..f43e7b430 100644 --- a/include/__locale +++ b/include/__locale @@ -469,7 +469,7 @@ public: static const mask alnum = alpha | digit; static const mask graph = alnum | punct; - _LIBCPP_ALWAYS_INLINE ctype_base() {} + _LIBCPP_INLINE_VISIBILITY ctype_base() {} }; template class _LIBCPP_TEMPLATE_VIS ctype; @@ -482,77 +482,77 @@ class _LIBCPP_TYPE_VIS ctype public: typedef wchar_t char_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit ctype(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool is(mask __m, char_type __c) const { return do_is(__m, __c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const { return do_is(__low, __high, __vec); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* scan_is(mask __m, const char_type* __low, const char_type* __high) const { return do_scan_is(__m, __low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const { return do_scan_not(__m, __low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type toupper(char_type __c) const { return do_toupper(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* toupper(char_type* __low, const char_type* __high) const { return do_toupper(__low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type tolower(char_type __c) const { return do_tolower(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* tolower(char_type* __low, const char_type* __high) const { return do_tolower(__low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type widen(char __c) const { return do_widen(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char* widen(const char* __low, const char* __high, char_type* __to) const { return do_widen(__low, __high, __to); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char narrow(char_type __c, char __dfault) const { return do_narrow(__c, __dfault); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const { return do_narrow(__low, __high, __dfault, __to); @@ -587,13 +587,13 @@ public: explicit ctype(const mask* __tab = 0, bool __del = false, size_t __refs = 0); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool is(mask __m, char_type __c) const { return isascii(__c) ? (__tab_[static_cast(__c)] & __m) !=0 : false; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* is(const char_type* __low, const char_type* __high, mask* __vec) const { for (; __low != __high; ++__low, ++__vec) @@ -601,7 +601,7 @@ public: return __low; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* scan_is (mask __m, const char_type* __low, const char_type* __high) const { for (; __low != __high; ++__low) @@ -610,7 +610,7 @@ public: return __low; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* scan_not(mask __m, const char_type* __low, const char_type* __high) const { for (; __low != __high; ++__low) @@ -619,49 +619,49 @@ public: return __low; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type toupper(char_type __c) const { return do_toupper(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* toupper(char_type* __low, const char_type* __high) const { return do_toupper(__low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type tolower(char_type __c) const { return do_tolower(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char_type* tolower(char_type* __low, const char_type* __high) const { return do_tolower(__low, __high); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char_type widen(char __c) const { return do_widen(__c); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char* widen(const char* __low, const char* __high, char_type* __to) const { return do_widen(__low, __high, __to); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY char narrow(char_type __c, char __dfault) const { return do_narrow(__c, __dfault); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const char* narrow(const char_type* __low, const char_type* __high, char __dfault, char* __to) const { return do_narrow(__low, __high, __dfault, __to); @@ -674,7 +674,7 @@ public: #else static const size_t table_size = 256; // FIXME: Don't hardcode this. #endif - _LIBCPP_ALWAYS_INLINE const mask* table() const _NOEXCEPT {return __tab_;} + _LIBCPP_INLINE_VISIBILITY const mask* table() const _NOEXCEPT {return __tab_;} static const mask* classic_table() _NOEXCEPT; #if defined(__GLIBC__) || defined(__EMSCRIPTEN__) static const int* __classic_upper_table() _NOEXCEPT; @@ -854,7 +854,7 @@ tolower(_CharT __c, const locale& __loc) class _LIBCPP_TYPE_VIS codecvt_base { public: - _LIBCPP_ALWAYS_INLINE codecvt_base() {} + _LIBCPP_INLINE_VISIBILITY codecvt_base() {} enum result {ok, partial, error, noconv}; }; @@ -874,11 +874,11 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -886,14 +886,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -901,25 +901,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int max_length() const _NOEXCEPT { return do_max_length(); @@ -928,7 +928,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {} @@ -963,7 +963,7 @@ public: explicit codecvt(size_t __refs = 0); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -971,14 +971,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -986,25 +986,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int max_length() const _NOEXCEPT { return do_max_length(); @@ -1043,11 +1043,11 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -1055,14 +1055,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -1070,25 +1070,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int max_length() const _NOEXCEPT { return do_max_length(); @@ -1097,7 +1097,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {} @@ -1129,11 +1129,11 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result out(state_type& __st, const intern_type* __frm, const intern_type* __frm_end, const intern_type*& __frm_nxt, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const @@ -1141,14 +1141,14 @@ public: return do_out(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result unshift(state_type& __st, extern_type* __to, extern_type* __to_end, extern_type*& __to_nxt) const { return do_unshift(__st, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY result in(state_type& __st, const extern_type* __frm, const extern_type* __frm_end, const extern_type*& __frm_nxt, intern_type* __to, intern_type* __to_end, intern_type*& __to_nxt) const @@ -1156,25 +1156,25 @@ public: return do_in(__st, __frm, __frm_end, __frm_nxt, __to, __to_end, __to_nxt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int encoding() const _NOEXCEPT { return do_encoding(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool always_noconv() const _NOEXCEPT { return do_always_noconv(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int length(state_type& __st, const extern_type* __frm, const extern_type* __end, size_t __mx) const { return do_length(__st, __frm, __end, __mx); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int max_length() const _NOEXCEPT { return do_max_length(); @@ -1183,7 +1183,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt(const char*, size_t __refs = 0) : locale::facet(__refs) {} @@ -1210,10 +1210,10 @@ class _LIBCPP_TEMPLATE_VIS codecvt_byname : public codecvt<_InternT, _ExternT, _StateT> { public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt_byname(const char* __nm, size_t __refs = 0) : codecvt<_InternT, _ExternT, _StateT>(__nm, __refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt_byname(const string& __nm, size_t __refs = 0) : codecvt<_InternT, _ExternT, _StateT>(__nm.c_str(), __refs) {} protected: @@ -1244,7 +1244,7 @@ template <> struct __narrow_to_utf8<8> { template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const { @@ -1258,13 +1258,13 @@ template <> struct __narrow_to_utf8<16> : public codecvt { - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY __narrow_to_utf8() : codecvt(1) {} ~__narrow_to_utf8(); template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const { @@ -1292,13 +1292,13 @@ template <> struct __narrow_to_utf8<32> : public codecvt { - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY __narrow_to_utf8() : codecvt(1) {} ~__narrow_to_utf8(); template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const _CharT* __wb, const _CharT* __we) const { @@ -1334,7 +1334,7 @@ template <> struct __widen_from_utf8<8> { template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const { @@ -1348,13 +1348,13 @@ template <> struct __widen_from_utf8<16> : public codecvt { - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY __widen_from_utf8() : codecvt(1) {} ~__widen_from_utf8(); template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const { @@ -1382,13 +1382,13 @@ template <> struct __widen_from_utf8<32> : public codecvt { - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY __widen_from_utf8() : codecvt(1) {} ~__widen_from_utf8(); template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _OutputIterator operator()(_OutputIterator __s, const char* __nb, const char* __ne) const { @@ -1426,11 +1426,11 @@ public: explicit numpunct(size_t __refs = 0); - _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} - _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} - _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} - _LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();} - _LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();} + _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();} + _LIBCPP_INLINE_VISIBILITY string_type truename() const {return do_truename();} + _LIBCPP_INLINE_VISIBILITY string_type falsename() const {return do_falsename();} static locale::id id; @@ -1457,11 +1457,11 @@ public: explicit numpunct(size_t __refs = 0); - _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} - _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} - _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} - _LIBCPP_ALWAYS_INLINE string_type truename() const {return do_truename();} - _LIBCPP_ALWAYS_INLINE string_type falsename() const {return do_falsename();} + _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();} + _LIBCPP_INLINE_VISIBILITY string_type truename() const {return do_truename();} + _LIBCPP_INLINE_VISIBILITY string_type falsename() const {return do_falsename();} static locale::id id; diff --git a/include/__nullptr b/include/__nullptr index a341234f5..aa3b4d214 100644 --- a/include/__nullptr +++ b/include/__nullptr @@ -27,24 +27,24 @@ struct _LIBCPP_TEMPLATE_VIS nullptr_t struct __nat {int __for_bool_;}; - _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {} - _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {} - _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;} template - _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator _Tp* () const {return 0;} template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY operator _Tp _Up::* () const {return 0;} - friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;} - friend _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;} + friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;} + friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;} }; -inline _LIBCPP_ALWAYS_INLINE _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);} +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);} #define nullptr _VSTD::__get_nullptr_t() diff --git a/include/any b/include/any index d7161b0d6..9bd2f53c5 100644 --- a/include/any +++ b/include/any @@ -104,7 +104,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 14 -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_any_cast() { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -304,7 +304,7 @@ private: __any_imp::_Buffer __buf; }; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void * __call(_Action __a, any * __other = nullptr, type_info const * __info = nullptr, const void* __fallback_info = nullptr) const @@ -312,7 +312,7 @@ private: return __h(__a, this, __other, __info, __fallback_info); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void * __call(_Action __a, any * __other = nullptr, type_info const * __info = nullptr, const void* __fallback_info = nullptr) diff --git a/include/cmath b/include/cmath index 917928a1f..ffb1c46c7 100644 --- a/include/cmath +++ b/include/cmath @@ -547,7 +547,7 @@ hypot(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT #endif template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -559,7 +559,7 @@ __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -567,7 +567,7 @@ __libcpp_isnan_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -579,7 +579,7 @@ __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -587,7 +587,7 @@ __libcpp_isinf_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT { @@ -599,7 +599,7 @@ __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT } template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR typename enable_if::value, bool>::type __libcpp_isfinite_or_builtin(_A1 __lcpp_x) _NOEXCEPT { diff --git a/include/codecvt b/include/codecvt index 46f56acff..5eb9d1549 100644 --- a/include/codecvt +++ b/include/codecvt @@ -86,7 +86,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -121,7 +121,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -156,7 +156,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -186,11 +186,11 @@ class _LIBCPP_TEMPLATE_VIS codecvt_utf8 : public __codecvt_utf8<_Elem> { public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt_utf8(size_t __refs = 0) : __codecvt_utf8<_Elem>(__refs, _Maxcode, _Mode) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~codecvt_utf8() {} }; @@ -209,7 +209,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -244,7 +244,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -279,7 +279,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -314,7 +314,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -349,7 +349,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -384,7 +384,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -414,11 +414,11 @@ class _LIBCPP_TEMPLATE_VIS codecvt_utf16 : public __codecvt_utf16<_Elem, _Mode & little_endian> { public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt_utf16(size_t __refs = 0) : __codecvt_utf16<_Elem, _Mode & little_endian>(__refs, _Maxcode, _Mode) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~codecvt_utf16() {} }; @@ -437,7 +437,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -472,7 +472,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -507,7 +507,7 @@ public: typedef char extern_type; typedef mbstate_t state_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit __codecvt_utf8_utf16(size_t __refs, unsigned long _Maxcode, codecvt_mode _Mode) : codecvt(__refs), _Maxcode_(_Maxcode), @@ -537,11 +537,11 @@ class _LIBCPP_TEMPLATE_VIS codecvt_utf8_utf16 : public __codecvt_utf8_utf16<_Elem> { public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit codecvt_utf8_utf16(size_t __refs = 0) : __codecvt_utf8_utf16<_Elem>(__refs, _Maxcode, _Mode) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~codecvt_utf8_utf16() {} }; diff --git a/include/exception b/include/exception index 79bd6ac2a..b517486b5 100644 --- a/include/exception +++ b/include/exception @@ -259,7 +259,7 @@ struct __throw_with_nested; template struct __throw_with_nested<_Tp, _Up, true> { - _LIBCPP_NORETURN static inline _LIBCPP_ALWAYS_INLINE void + _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void #ifndef _LIBCPP_CXX03_LANG __do_throw(_Tp&& __t) #else @@ -272,7 +272,7 @@ struct __throw_with_nested<_Tp, _Up, true> { template struct __throw_with_nested<_Tp, _Up, false> { - _LIBCPP_NORETURN static inline _LIBCPP_ALWAYS_INLINE void + _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void #ifndef _LIBCPP_CXX03_LANG __do_throw(_Tp&& __t) #else diff --git a/include/experimental/dynarray b/include/experimental/dynarray index cebfc208d..a60c87c3f 100644 --- a/include/experimental/dynarray +++ b/include/experimental/dynarray @@ -133,7 +133,7 @@ public: private: size_t __size_; value_type * __base_; - _LIBCPP_ALWAYS_INLINE dynarray () noexcept : __size_(0), __base_(nullptr) {} + _LIBCPP_INLINE_VISIBILITY dynarray () noexcept : __size_(0), __base_(nullptr) {} static inline _LIBCPP_INLINE_VISIBILITY value_type* __allocate(size_t __count) { diff --git a/include/experimental/filesystem b/include/experimental/filesystem index f29e23e18..1ca179699 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -470,23 +470,23 @@ public: file_status& operator=(file_status&&) _NOEXCEPT = default; // observers - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY file_type type() const _NOEXCEPT { return __ft_; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY perms permissions() const _NOEXCEPT { return __prms_; } // modifiers - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void type(file_type __ft) _NOEXCEPT { __ft_ = __ft; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void permissions(perms __p) _NOEXCEPT { __prms_ = __p; } @@ -1106,7 +1106,7 @@ private: string_type __pn_; }; -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) _NOEXCEPT { __lhs.swap(__rhs); } @@ -1298,7 +1298,7 @@ private: }; template -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_NO_EXCEPTIONS void __throw_filesystem_error(_Args && ...__args) { diff --git a/include/functional b/include/functional index bb0bdf151..80261895e 100644 --- a/include/functional +++ b/include/functional @@ -1399,7 +1399,7 @@ public: #endif }; -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_function_call() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/future b/include/future index 536574e75..528091b04 100644 --- a/include/future +++ b/include/future @@ -514,7 +514,7 @@ public: virtual ~future_error() _NOEXCEPT; }; -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_NO_EXCEPTIONS _LIBCPP_AVAILABILITY_FUTURE_ERROR #endif diff --git a/include/initializer_list b/include/initializer_list index 8c234aaaa..b934637b8 100644 --- a/include/initializer_list +++ b/include/initializer_list @@ -61,7 +61,7 @@ class _LIBCPP_TEMPLATE_VIS initializer_list const _Ep* __begin_; size_t __size_; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 initializer_list(const _Ep* __b, size_t __s) _NOEXCEPT : __begin_(__b), @@ -76,19 +76,19 @@ public: typedef const _Ep* iterator; typedef const _Ep* const_iterator; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 initializer_list() _NOEXCEPT : __begin_(nullptr), __size_(0) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 size_t size() const _NOEXCEPT {return __size_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const _Ep* begin() const _NOEXCEPT {return __begin_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const _Ep* end() const _NOEXCEPT {return __begin_ + __size_;} }; diff --git a/include/ios b/include/ios index 6e32d0fe6..040b2d4e0 100644 --- a/include/ios +++ b/include/ios @@ -337,9 +337,9 @@ protected: } void init(void* __sb); - _LIBCPP_ALWAYS_INLINE void* rdbuf() const {return __rdbuf_;} + _LIBCPP_INLINE_VISIBILITY void* rdbuf() const {return __rdbuf_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void rdbuf(void* __sb) { __rdbuf_ = __sb; @@ -351,7 +351,7 @@ protected: void move(ios_base&); void swap(ios_base&) _NOEXCEPT; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void set_rdbuf(void* __sb) { __rdbuf_ = __sb; @@ -599,26 +599,26 @@ public: // we give it internal linkage. #if defined(_LIBCPP_CXX03_LANG) - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY operator __cxx03_bool::__bool_type() const { return !fail() ? &__cxx03_bool::__true_value : nullptr; } #else - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const {return !fail();} #endif - _LIBCPP_ALWAYS_INLINE bool operator!() const {return fail();} - _LIBCPP_ALWAYS_INLINE iostate rdstate() const {return ios_base::rdstate();} - _LIBCPP_ALWAYS_INLINE void clear(iostate __state = goodbit) {ios_base::clear(__state);} - _LIBCPP_ALWAYS_INLINE void setstate(iostate __state) {ios_base::setstate(__state);} - _LIBCPP_ALWAYS_INLINE bool good() const {return ios_base::good();} - _LIBCPP_ALWAYS_INLINE bool eof() const {return ios_base::eof();} - _LIBCPP_ALWAYS_INLINE bool fail() const {return ios_base::fail();} - _LIBCPP_ALWAYS_INLINE bool bad() const {return ios_base::bad();} + _LIBCPP_INLINE_VISIBILITY bool operator!() const {return fail();} + _LIBCPP_INLINE_VISIBILITY iostate rdstate() const {return ios_base::rdstate();} + _LIBCPP_INLINE_VISIBILITY void clear(iostate __state = goodbit) {ios_base::clear(__state);} + _LIBCPP_INLINE_VISIBILITY void setstate(iostate __state) {ios_base::setstate(__state);} + _LIBCPP_INLINE_VISIBILITY bool good() const {return ios_base::good();} + _LIBCPP_INLINE_VISIBILITY bool eof() const {return ios_base::eof();} + _LIBCPP_INLINE_VISIBILITY bool fail() const {return ios_base::fail();} + _LIBCPP_INLINE_VISIBILITY bool bad() const {return ios_base::bad();} - _LIBCPP_ALWAYS_INLINE iostate exceptions() const {return ios_base::exceptions();} - _LIBCPP_ALWAYS_INLINE void exceptions(iostate __iostate) {ios_base::exceptions(__iostate);} + _LIBCPP_INLINE_VISIBILITY iostate exceptions() const {return ios_base::exceptions();} + _LIBCPP_INLINE_VISIBILITY void exceptions(iostate __iostate) {ios_base::exceptions(__iostate);} // 27.5.4.1 Constructor/destructor: _LIBCPP_INLINE_VISIBILITY @@ -652,7 +652,7 @@ public: char_type widen(char __c) const; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY basic_ios() {// purposefully does no initialization } _LIBCPP_INLINE_VISIBILITY @@ -661,7 +661,7 @@ protected: _LIBCPP_INLINE_VISIBILITY void move(basic_ios& __rhs); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void move(basic_ios&& __rhs) {move(__rhs);} #endif _LIBCPP_INLINE_VISIBILITY diff --git a/include/locale b/include/locale index 52885b768..e240799f3 100644 --- a/include/locale +++ b/include/locale @@ -573,81 +573,81 @@ public: typedef _CharT char_type; typedef _InputIterator iter_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit num_get(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned short& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned int& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, unsigned long long& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, float& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, double& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { return do_get(__b, __e, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { @@ -657,7 +657,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~num_get() {} template @@ -1261,60 +1261,60 @@ public: typedef _CharT char_type; typedef _OutputIterator iter_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit num_put(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, bool __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, unsigned long long __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, double __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, long double __v) const { return do_put(__s, __iob, __fl, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const void* __v) const { @@ -1324,7 +1324,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~num_put() {} virtual iter_type do_put(iter_type __s, ios_base& __iob, char_type __fl, @@ -1738,7 +1738,7 @@ protected: virtual const string_type& __x() const; virtual const string_type& __X() const; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~__time_get_c_storage() {} }; @@ -1770,52 +1770,52 @@ public: typedef time_base::dateorder dateorder; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_get(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY dateorder date_order() const { return this->do_date_order(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get_time(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_time(__b, __e, __iob, __err, __tm); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get_date(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_date(__b, __e, __iob, __err, __tm); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get_weekday(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_weekday(__b, __e, __iob, __err, __tm); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get_monthname(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_monthname(__b, __e, __iob, __err, __tm); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get_year(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm* __tm) const { return do_get_year(__b, __e, __iob, __err, __tm); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, tm *__tm, char __fmt, char __mod = 0) const @@ -1830,7 +1830,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~time_get() {} virtual dateorder do_date_order() const; @@ -2399,7 +2399,7 @@ protected: explicit __time_get_storage(const char* __nm); explicit __time_get_storage(const string& __nm); - _LIBCPP_ALWAYS_INLINE ~__time_get_storage() {} + _LIBCPP_INLINE_VISIBILITY ~__time_get_storage() {} time_base::dateorder __do_date_order() const; @@ -2458,7 +2458,7 @@ class _LIBCPP_TYPE_VIS __time_put { locale_t __loc_; protected: - _LIBCPP_ALWAYS_INLINE __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} + _LIBCPP_INLINE_VISIBILITY __time_put() : __loc_(_LIBCPP_GET_C_LOCALE) {} __time_put(const char* __nm); __time_put(const string& __nm); ~__time_put(); @@ -2477,14 +2477,14 @@ public: typedef _CharT char_type; typedef _OutputIterator iter_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_put(size_t __refs = 0) : locale::facet(__refs) {} iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, const char_type* __pb, const char_type* __pe) const; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, ios_base& __iob, char_type __fl, const tm* __tm, char __fmt, char __mod = 0) const { @@ -2494,16 +2494,16 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~time_put() {} virtual iter_type do_put(iter_type __s, ios_base&, char_type, const tm* __tm, char __fmt, char __mod) const; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_put(const char* __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_put(const string& __nm, size_t __refs) : locale::facet(__refs), __time_put(__nm) {} @@ -2572,16 +2572,16 @@ class _LIBCPP_TEMPLATE_VIS time_put_byname : public time_put<_CharT, _OutputIterator> { public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_put_byname(const char* __nm, size_t __refs = 0) : time_put<_CharT, _OutputIterator>(__nm, __refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit time_put_byname(const string& __nm, size_t __refs = 0) : time_put<_CharT, _OutputIterator>(__nm, __refs) {} protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~time_put_byname() {} }; @@ -2596,7 +2596,7 @@ public: enum part {none, space, symbol, sign, value}; struct pattern {char field[4];}; - _LIBCPP_ALWAYS_INLINE money_base() {} + _LIBCPP_INLINE_VISIBILITY money_base() {} }; // moneypunct @@ -2610,25 +2610,25 @@ public: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE char_type decimal_point() const {return do_decimal_point();} - _LIBCPP_ALWAYS_INLINE char_type thousands_sep() const {return do_thousands_sep();} - _LIBCPP_ALWAYS_INLINE string grouping() const {return do_grouping();} - _LIBCPP_ALWAYS_INLINE string_type curr_symbol() const {return do_curr_symbol();} - _LIBCPP_ALWAYS_INLINE string_type positive_sign() const {return do_positive_sign();} - _LIBCPP_ALWAYS_INLINE string_type negative_sign() const {return do_negative_sign();} - _LIBCPP_ALWAYS_INLINE int frac_digits() const {return do_frac_digits();} - _LIBCPP_ALWAYS_INLINE pattern pos_format() const {return do_pos_format();} - _LIBCPP_ALWAYS_INLINE pattern neg_format() const {return do_neg_format();} + _LIBCPP_INLINE_VISIBILITY char_type decimal_point() const {return do_decimal_point();} + _LIBCPP_INLINE_VISIBILITY char_type thousands_sep() const {return do_thousands_sep();} + _LIBCPP_INLINE_VISIBILITY string grouping() const {return do_grouping();} + _LIBCPP_INLINE_VISIBILITY string_type curr_symbol() const {return do_curr_symbol();} + _LIBCPP_INLINE_VISIBILITY string_type positive_sign() const {return do_positive_sign();} + _LIBCPP_INLINE_VISIBILITY string_type negative_sign() const {return do_negative_sign();} + _LIBCPP_INLINE_VISIBILITY int frac_digits() const {return do_frac_digits();} + _LIBCPP_INLINE_VISIBILITY pattern pos_format() const {return do_pos_format();} + _LIBCPP_INLINE_VISIBILITY pattern neg_format() const {return do_neg_format();} static locale::id id; static const bool intl = _International; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~moneypunct() {} virtual char_type do_decimal_point() const {return numeric_limits::max();} @@ -2668,16 +2668,16 @@ public: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit moneypunct_byname(const char* __nm, size_t __refs = 0) : moneypunct<_CharT, _International>(__refs) {init(__nm);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit moneypunct_byname(const string& __nm, size_t __refs = 0) : moneypunct<_CharT, _International>(__refs) {init(__nm.c_str());} protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~moneypunct_byname() {} virtual char_type do_decimal_point() const {return __decimal_point_;} @@ -2723,7 +2723,7 @@ protected: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE __money_get() {} + _LIBCPP_INLINE_VISIBILITY __money_get() {} static void __gather_info(bool __intl, const locale& __loc, money_base::pattern& __pat, char_type& __dp, @@ -2781,18 +2781,18 @@ public: typedef _InputIterator iter_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit money_get(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const { return do_get(__b, __e, __intl, __iob, __err, __v); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const { @@ -2803,7 +2803,7 @@ public: protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~money_get() {} virtual iter_type do_get(iter_type __b, iter_type __e, bool __intl, @@ -3163,7 +3163,7 @@ protected: typedef _CharT char_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE __money_put() {} + _LIBCPP_INLINE_VISIBILITY __money_put() {} static void __gather_info(bool __intl, bool __neg, const locale& __loc, money_base::pattern& __pat, char_type& __dp, @@ -3339,18 +3339,18 @@ public: typedef _OutputIterator iter_type; typedef basic_string string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit money_put(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const { return do_put(__s, __intl, __iob, __fl, __units); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY iter_type put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const { @@ -3360,7 +3360,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~money_put() {} virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, @@ -3489,7 +3489,7 @@ class _LIBCPP_TYPE_VIS messages_base public: typedef ptrdiff_t catalog; - _LIBCPP_ALWAYS_INLINE messages_base() {} + _LIBCPP_INLINE_VISIBILITY messages_base() {} }; template @@ -3501,24 +3501,24 @@ public: typedef _CharT char_type; typedef basic_string<_CharT> string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit messages(size_t __refs = 0) : locale::facet(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY catalog open(const basic_string& __nm, const locale& __loc) const { return do_open(__nm, __loc); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY string_type get(catalog __c, int __set, int __msgid, const string_type& __dflt) const { return do_get(__c, __set, __msgid, __dflt); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void close(catalog __c) const { do_close(__c); @@ -3527,7 +3527,7 @@ public: static locale::id id; protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~messages() {} virtual catalog do_open(const basic_string&, const locale&) const; @@ -3600,16 +3600,16 @@ public: typedef messages_base::catalog catalog; typedef basic_string<_CharT> string_type; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit messages_byname(const char*, size_t __refs = 0) : messages<_CharT>(__refs) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY explicit messages_byname(const string&, size_t __refs = 0) : messages<_CharT>(__refs) {} protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY ~messages_byname() {} }; @@ -3637,43 +3637,43 @@ private: wstring_convert(const wstring_convert& __wc); wstring_convert& operator=(const wstring_convert& __wc); public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(_Codecvt* __pcvt = new _Codecvt); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY wstring_convert(_Codecvt* __pcvt, state_type __state); _LIBCPP_EXPLICIT_AFTER_CXX11 wstring_convert(const byte_string& __byte_err, const wide_string& __wide_err = wide_string()); #ifndef _LIBCPP_CXX03_LANG - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY wstring_convert(wstring_convert&& __wc); #endif ~wstring_convert(); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY wide_string from_bytes(char __byte) {return from_bytes(&__byte, &__byte+1);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY wide_string from_bytes(const char* __ptr) {return from_bytes(__ptr, __ptr + char_traits::length(__ptr));} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY wide_string from_bytes(const byte_string& __str) {return from_bytes(__str.data(), __str.data() + __str.size());} wide_string from_bytes(const char* __first, const char* __last); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY byte_string to_bytes(_Elem __wchar) {return to_bytes(&__wchar, &__wchar+1);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY byte_string to_bytes(const _Elem* __wptr) {return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY byte_string to_bytes(const wide_string& __wstr) {return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());} byte_string to_bytes(const _Elem* __first, const _Elem* __last); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY size_t converted() const _NOEXCEPT {return __cvtcount_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY state_type state() const {return __cvtstate_;} }; diff --git a/include/math.h b/include/math.h index 658ba93be..3cc72aa27 100644 --- a/include/math.h +++ b/include/math.h @@ -314,7 +314,7 @@ extern "C++" { #ifdef signbit template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_signbit(_A1 __lcpp_x) _NOEXCEPT { @@ -376,7 +376,7 @@ signbit(_A1) _NOEXCEPT #ifdef fpclassify template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY int __libcpp_fpclassify(_A1 __lcpp_x) _NOEXCEPT { @@ -422,7 +422,7 @@ fpclassify(_A1 __lcpp_x) _NOEXCEPT #ifdef isfinite template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isfinite(_A1 __lcpp_x) _NOEXCEPT { @@ -456,7 +456,7 @@ isfinite(_A1) _NOEXCEPT #ifdef isinf template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isinf(_A1 __lcpp_x) _NOEXCEPT { @@ -504,7 +504,7 @@ isinf(long double __lcpp_x) _NOEXCEPT { return __libcpp_isinf(__lcpp_x); } #ifdef isnan template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isnan(_A1 __lcpp_x) _NOEXCEPT { @@ -548,7 +548,7 @@ isnan(long double __lcpp_x) _NOEXCEPT { return __libcpp_isnan(__lcpp_x); } #ifdef isnormal template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isnormal(_A1 __lcpp_x) _NOEXCEPT { @@ -578,7 +578,7 @@ isnormal(_A1 __lcpp_x) _NOEXCEPT #ifdef isgreater template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -608,7 +608,7 @@ isgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef isgreaterequal template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isgreaterequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -638,7 +638,7 @@ isgreaterequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef isless template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isless(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -668,7 +668,7 @@ isless(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef islessequal template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_islessequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -698,7 +698,7 @@ islessequal(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef islessgreater template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_islessgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { @@ -728,7 +728,7 @@ islessgreater(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT #ifdef isunordered template -_LIBCPP_ALWAYS_INLINE +_LIBCPP_INLINE_VISIBILITY bool __libcpp_isunordered(_A1 __lcpp_x, _A2 __lcpp_y) _NOEXCEPT { diff --git a/include/memory b/include/memory index 31d4e4fac..fd830d7ed 100644 --- a/include/memory +++ b/include/memory @@ -679,7 +679,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD template -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY _ValueType __libcpp_relaxed_load(_ValueType const* __value) { #if !defined(_LIBCPP_HAS_NO_THREADS) && \ defined(__ATOMIC_RELAXED) && \ @@ -691,7 +691,7 @@ _ValueType __libcpp_relaxed_load(_ValueType const* __value) { } template -inline _LIBCPP_ALWAYS_INLINE +inline _LIBCPP_INLINE_VISIBILITY _ValueType __libcpp_acquire_load(_ValueType const* __value) { #if !defined(_LIBCPP_HAS_NO_THREADS) && \ defined(__ATOMIC_ACQUIRE) && \ @@ -3483,7 +3483,7 @@ public: virtual const char* what() const _NOEXCEPT; }; -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_weak_ptr() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/new b/include/new index e42ffad27..b5dc05542 100644 --- a/include/new +++ b/include/new @@ -281,7 +281,7 @@ inline _LIBCPP_INLINE_VISIBILITY void __libcpp_deallocate(void* __ptr, size_t __ } #ifdef _LIBCPP_BAD_ARRAY_LENGTH_DEFINED -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY #ifndef _LIBCPP_NO_EXCEPTIONS _LIBCPP_AVAILABILITY_BAD_ARRAY_LENGTH #endif diff --git a/include/ostream b/include/ostream index 197636eac..5404e0dca 100644 --- a/include/ostream +++ b/include/ostream @@ -232,7 +232,7 @@ public: basic_ostream& seekp(off_type __off, ios_base::seekdir __dir); protected: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY basic_ostream() {} // extension, intentially does not initialize }; @@ -249,7 +249,7 @@ public: explicit sentry(basic_ostream<_CharT, _Traits>& __os); ~sentry(); - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const {return __ok_;} }; diff --git a/include/regex b/include/regex index 612fa84ce..84aacc029 100644 --- a/include/regex +++ b/include/regex @@ -968,7 +968,7 @@ public: }; template -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_regex_error() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/stdexcept b/include/stdexcept index 95a96cc07..6533497e4 100644 --- a/include/stdexcept +++ b/include/stdexcept @@ -185,7 +185,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD // in the dylib _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_runtime_error(const char*); -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_logic_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -196,7 +196,7 @@ void __throw_logic_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_domain_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -207,7 +207,7 @@ void __throw_domain_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_invalid_argument(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -218,7 +218,7 @@ void __throw_invalid_argument(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_length_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -229,7 +229,7 @@ void __throw_length_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_out_of_range(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -240,7 +240,7 @@ void __throw_out_of_range(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_range_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -251,7 +251,7 @@ void __throw_range_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_overflow_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS @@ -262,7 +262,7 @@ void __throw_overflow_error(const char*__msg) #endif } -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_underflow_error(const char*__msg) { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/streambuf b/include/streambuf index e409d2106..37a653237 100644 --- a/include/streambuf +++ b/include/streambuf @@ -236,9 +236,9 @@ protected: void swap(basic_streambuf& __rhs); // 27.6.2.3.2 Get area: - _LIBCPP_ALWAYS_INLINE char_type* eback() const {return __binp_;} - _LIBCPP_ALWAYS_INLINE char_type* gptr() const {return __ninp_;} - _LIBCPP_ALWAYS_INLINE char_type* egptr() const {return __einp_;} + _LIBCPP_INLINE_VISIBILITY char_type* eback() const {return __binp_;} + _LIBCPP_INLINE_VISIBILITY char_type* gptr() const {return __ninp_;} + _LIBCPP_INLINE_VISIBILITY char_type* egptr() const {return __einp_;} inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY void gbump(int __n) { __ninp_ += __n; } @@ -251,14 +251,14 @@ protected: } // 27.6.2.3.3 Put area: - _LIBCPP_ALWAYS_INLINE char_type* pbase() const {return __bout_;} - _LIBCPP_ALWAYS_INLINE char_type* pptr() const {return __nout_;} - _LIBCPP_ALWAYS_INLINE char_type* epptr() const {return __eout_;} + _LIBCPP_INLINE_VISIBILITY char_type* pbase() const {return __bout_;} + _LIBCPP_INLINE_VISIBILITY char_type* pptr() const {return __nout_;} + _LIBCPP_INLINE_VISIBILITY char_type* epptr() const {return __eout_;} inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY void pbump(int __n) { __nout_ += __n; } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void __pbump(streamsize __n) { __nout_ += __n; } inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY diff --git a/include/support/android/locale_bionic.h b/include/support/android/locale_bionic.h index d638757fd..50fcf5c36 100644 --- a/include/support/android/locale_bionic.h +++ b/include/support/android/locale_bionic.h @@ -40,18 +40,18 @@ extern "C" { extern "C" { #endif -inline _LIBCPP_ALWAYS_INLINE float strtof_l(const char* __nptr, char** __endptr, - locale_t) { +inline _LIBCPP_INLINE_VISIBILITY float strtof_l(const char* __nptr, char** __endptr, + locale_t) { return ::strtof(__nptr, __endptr); } -inline _LIBCPP_ALWAYS_INLINE double strtod_l(const char* __nptr, - char** __endptr, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY double strtod_l(const char* __nptr, + char** __endptr, locale_t) { return ::strtod(__nptr, __endptr); } -inline _LIBCPP_ALWAYS_INLINE long strtol_l(const char* __nptr, char** __endptr, - int __base, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY long strtol_l(const char* __nptr, char** __endptr, + int __base, locale_t) { return ::strtol(__nptr, __endptr, __base); } diff --git a/include/support/xlocale/__posix_l_fallback.h b/include/support/xlocale/__posix_l_fallback.h index c893a6731..b9a0939f8 100644 --- a/include/support/xlocale/__posix_l_fallback.h +++ b/include/support/xlocale/__posix_l_fallback.h @@ -20,141 +20,141 @@ extern "C" { #endif -inline _LIBCPP_ALWAYS_INLINE int isalnum_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isalnum_l(int c, locale_t) { return ::isalnum(c); } -inline _LIBCPP_ALWAYS_INLINE int isalpha_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isalpha_l(int c, locale_t) { return ::isalpha(c); } -inline _LIBCPP_ALWAYS_INLINE int isblank_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isblank_l(int c, locale_t) { return ::isblank(c); } -inline _LIBCPP_ALWAYS_INLINE int iscntrl_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iscntrl_l(int c, locale_t) { return ::iscntrl(c); } -inline _LIBCPP_ALWAYS_INLINE int isdigit_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isdigit_l(int c, locale_t) { return ::isdigit(c); } -inline _LIBCPP_ALWAYS_INLINE int isgraph_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isgraph_l(int c, locale_t) { return ::isgraph(c); } -inline _LIBCPP_ALWAYS_INLINE int islower_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int islower_l(int c, locale_t) { return ::islower(c); } -inline _LIBCPP_ALWAYS_INLINE int isprint_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isprint_l(int c, locale_t) { return ::isprint(c); } -inline _LIBCPP_ALWAYS_INLINE int ispunct_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int ispunct_l(int c, locale_t) { return ::ispunct(c); } -inline _LIBCPP_ALWAYS_INLINE int isspace_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isspace_l(int c, locale_t) { return ::isspace(c); } -inline _LIBCPP_ALWAYS_INLINE int isupper_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isupper_l(int c, locale_t) { return ::isupper(c); } -inline _LIBCPP_ALWAYS_INLINE int isxdigit_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int isxdigit_l(int c, locale_t) { return ::isxdigit(c); } -inline _LIBCPP_ALWAYS_INLINE int iswalnum_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswalnum_l(wint_t c, locale_t) { return ::iswalnum(c); } -inline _LIBCPP_ALWAYS_INLINE int iswalpha_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswalpha_l(wint_t c, locale_t) { return ::iswalpha(c); } -inline _LIBCPP_ALWAYS_INLINE int iswblank_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswblank_l(wint_t c, locale_t) { return ::iswblank(c); } -inline _LIBCPP_ALWAYS_INLINE int iswcntrl_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswcntrl_l(wint_t c, locale_t) { return ::iswcntrl(c); } -inline _LIBCPP_ALWAYS_INLINE int iswdigit_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswdigit_l(wint_t c, locale_t) { return ::iswdigit(c); } -inline _LIBCPP_ALWAYS_INLINE int iswgraph_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswgraph_l(wint_t c, locale_t) { return ::iswgraph(c); } -inline _LIBCPP_ALWAYS_INLINE int iswlower_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswlower_l(wint_t c, locale_t) { return ::iswlower(c); } -inline _LIBCPP_ALWAYS_INLINE int iswprint_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswprint_l(wint_t c, locale_t) { return ::iswprint(c); } -inline _LIBCPP_ALWAYS_INLINE int iswpunct_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswpunct_l(wint_t c, locale_t) { return ::iswpunct(c); } -inline _LIBCPP_ALWAYS_INLINE int iswspace_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswspace_l(wint_t c, locale_t) { return ::iswspace(c); } -inline _LIBCPP_ALWAYS_INLINE int iswupper_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswupper_l(wint_t c, locale_t) { return ::iswupper(c); } -inline _LIBCPP_ALWAYS_INLINE int iswxdigit_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int iswxdigit_l(wint_t c, locale_t) { return ::iswxdigit(c); } -inline _LIBCPP_ALWAYS_INLINE int toupper_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int toupper_l(int c, locale_t) { return ::toupper(c); } -inline _LIBCPP_ALWAYS_INLINE int tolower_l(int c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int tolower_l(int c, locale_t) { return ::tolower(c); } -inline _LIBCPP_ALWAYS_INLINE wint_t towupper_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY wint_t towupper_l(wint_t c, locale_t) { return ::towupper(c); } -inline _LIBCPP_ALWAYS_INLINE wint_t towlower_l(wint_t c, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY wint_t towlower_l(wint_t c, locale_t) { return ::towlower(c); } -inline _LIBCPP_ALWAYS_INLINE int strcoll_l(const char *s1, const char *s2, - locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int strcoll_l(const char *s1, const char *s2, + locale_t) { return ::strcoll(s1, s2); } -inline _LIBCPP_ALWAYS_INLINE size_t strxfrm_l(char *dest, const char *src, - size_t n, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY size_t strxfrm_l(char *dest, const char *src, + size_t n, locale_t) { return ::strxfrm(dest, src, n); } -inline _LIBCPP_ALWAYS_INLINE size_t strftime_l(char *s, size_t max, - const char *format, - const struct tm *tm, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY size_t strftime_l(char *s, size_t max, + const char *format, + const struct tm *tm, locale_t) { return ::strftime(s, max, format, tm); } -inline _LIBCPP_ALWAYS_INLINE int wcscoll_l(const wchar_t *ws1, - const wchar_t *ws2, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY int wcscoll_l(const wchar_t *ws1, + const wchar_t *ws2, locale_t) { return ::wcscoll(ws1, ws2); } -inline _LIBCPP_ALWAYS_INLINE size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, - size_t n, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, + size_t n, locale_t) { return ::wcsxfrm(dest, src, n); } diff --git a/include/support/xlocale/__strtonum_fallback.h b/include/support/xlocale/__strtonum_fallback.h index 4ae3918b3..50b4db354 100644 --- a/include/support/xlocale/__strtonum_fallback.h +++ b/include/support/xlocale/__strtonum_fallback.h @@ -20,43 +20,43 @@ extern "C" { #endif -inline _LIBCPP_ALWAYS_INLINE float strtof_l(const char *nptr, - char **endptr, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY float strtof_l(const char *nptr, + char **endptr, locale_t) { return ::strtof(nptr, endptr); } -inline _LIBCPP_ALWAYS_INLINE double strtod_l(const char *nptr, - char **endptr, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY double strtod_l(const char *nptr, + char **endptr, locale_t) { return ::strtod(nptr, endptr); } -inline _LIBCPP_ALWAYS_INLINE long double strtold_l(const char *nptr, - char **endptr, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY long double strtold_l(const char *nptr, + char **endptr, locale_t) { return ::strtold(nptr, endptr); } -inline _LIBCPP_ALWAYS_INLINE long long +inline _LIBCPP_INLINE_VISIBILITY long long strtoll_l(const char *nptr, char **endptr, int base, locale_t) { return ::strtoll(nptr, endptr, base); } -inline _LIBCPP_ALWAYS_INLINE unsigned long long +inline _LIBCPP_INLINE_VISIBILITY unsigned long long strtoull_l(const char *nptr, char **endptr, int base, locale_t) { return ::strtoull(nptr, endptr, base); } -inline _LIBCPP_ALWAYS_INLINE long long +inline _LIBCPP_INLINE_VISIBILITY long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr, int base, locale_t) { return ::wcstoll(nptr, endptr, base); } -inline _LIBCPP_ALWAYS_INLINE unsigned long long +inline _LIBCPP_INLINE_VISIBILITY unsigned long long wcstoull_l(const wchar_t *nptr, wchar_t **endptr, int base, locale_t) { return ::wcstoull(nptr, endptr, base); } -inline _LIBCPP_ALWAYS_INLINE long double wcstold_l(const wchar_t *nptr, - wchar_t **endptr, locale_t) { +inline _LIBCPP_INLINE_VISIBILITY long double wcstold_l(const wchar_t *nptr, + wchar_t **endptr, locale_t) { return ::wcstold(nptr, endptr); } diff --git a/include/system_error b/include/system_error index f5d8d1145..917c71029 100644 --- a/include/system_error +++ b/include/system_error @@ -203,7 +203,7 @@ public: defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) error_category() _NOEXCEPT; #else - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 error_category() _NOEXCEPT _LIBCPP_DEFAULT #endif private: @@ -217,13 +217,13 @@ public: virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT; virtual string message(int __ev) const = 0; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool operator==(const error_category& __rhs) const _NOEXCEPT {return this == &__rhs;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool operator!=(const error_category& __rhs) const _NOEXCEPT {return !(*this == __rhs);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY bool operator< (const error_category& __rhs) const _NOEXCEPT {return this < &__rhs;} friend class _LIBCPP_HIDDEN __do_message; @@ -244,21 +244,21 @@ class _LIBCPP_TYPE_VIS error_condition int __val_; const error_category* __cat_; public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_condition() _NOEXCEPT : __val_(0), __cat_(&generic_category()) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_condition(int __val, const error_category& __cat) _NOEXCEPT : __val_(__val), __cat_(&__cat) {} template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_condition(_Ep __e, typename enable_if::value>::type* = 0 ) _NOEXCEPT {*this = make_error_condition(__e);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void assign(int __val, const error_category& __cat) _NOEXCEPT { __val_ = __val; @@ -266,7 +266,7 @@ public: } template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY typename enable_if < is_error_condition_enum<_Ep>::value, @@ -275,21 +275,21 @@ public: operator=(_Ep __e) _NOEXCEPT {*this = make_error_condition(__e); return *this;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT { __val_ = 0; __cat_ = &generic_category(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int value() const _NOEXCEPT {return __val_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const error_category& category() const _NOEXCEPT {return *__cat_;} string message() const; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __val_ != 0;} }; @@ -316,21 +316,21 @@ class _LIBCPP_TYPE_VIS error_code int __val_; const error_category* __cat_; public: - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_code() _NOEXCEPT : __val_(0), __cat_(&system_category()) {} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_code(int __val, const error_category& __cat) _NOEXCEPT : __val_(__val), __cat_(&__cat) {} template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_code(_Ep __e, typename enable_if::value>::type* = 0 ) _NOEXCEPT {*this = make_error_code(__e);} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void assign(int __val, const error_category& __cat) _NOEXCEPT { __val_ = __val; @@ -338,7 +338,7 @@ public: } template - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY typename enable_if < is_error_code_enum<_Ep>::value, @@ -347,26 +347,26 @@ public: operator=(_Ep __e) _NOEXCEPT {*this = make_error_code(__e); return *this;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT { __val_ = 0; __cat_ = &system_category(); } - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY int value() const _NOEXCEPT {return __val_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const error_category& category() const _NOEXCEPT {return *__cat_;} - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY error_condition default_error_condition() const _NOEXCEPT {return __cat_->default_error_condition(__val_);} string message() const; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT {return __val_ != 0;} }; @@ -472,7 +472,7 @@ public: system_error(int __ev, const error_category& __ecat); ~system_error() _NOEXCEPT; - _LIBCPP_ALWAYS_INLINE + _LIBCPP_INLINE_VISIBILITY const error_code& code() const _NOEXCEPT {return __ec_;} private: diff --git a/include/typeinfo b/include/typeinfo index 74d94e9e3..f32ea6e76 100644 --- a/include/typeinfo +++ b/include/typeinfo @@ -226,7 +226,7 @@ public: #endif // defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME) _LIBCPP_BEGIN_NAMESPACE_STD -_LIBCPP_NORETURN inline _LIBCPP_ALWAYS_INLINE +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY void __throw_bad_cast() { #ifndef _LIBCPP_NO_EXCEPTIONS diff --git a/include/vector b/include/vector index 74c423ef2..0f5006f37 100644 --- a/include/vector +++ b/include/vector @@ -295,7 +295,7 @@ template class __vector_base_common { protected: - _LIBCPP_ALWAYS_INLINE __vector_base_common() {} + _LIBCPP_INLINE_VISIBILITY __vector_base_common() {} _LIBCPP_NORETURN void __throw_length_error() const; _LIBCPP_NORETURN void __throw_out_of_range() const; }; diff --git a/src/support/win32/thread_win32.cpp b/src/support/win32/thread_win32.cpp index 3f479443e..471049429 100644 --- a/src/support/win32/thread_win32.cpp +++ b/src/support/win32/thread_win32.cpp @@ -138,7 +138,7 @@ int __libcpp_condvar_destroy(__libcpp_condvar_t *__cv) } // Execute Once -static inline _LIBCPP_ALWAYS_INLINE BOOL CALLBACK +static inline _LIBCPP_INLINE_VISIBILITY BOOL CALLBACK __libcpp_init_once_execute_once_thunk(PINIT_ONCE __init_once, PVOID __parameter, PVOID *__context) { @@ -178,7 +178,7 @@ struct __libcpp_beginthreadex_thunk_data void *__arg; }; -static inline _LIBCPP_ALWAYS_INLINE unsigned WINAPI +static inline _LIBCPP_INLINE_VISIBILITY unsigned WINAPI __libcpp_beginthreadex_thunk(void *__raw_data) { auto *__data = -- GitLab From fbb1e6166ae4db034b339d558dc70d4e2d7ea4a9 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Thu, 12 Jul 2018 02:55:01 +0000 Subject: [PATCH 026/495] Turns out that wide literals U"xxx" and u"xxx" are c++11 and later. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@336880 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/std/strings/string.view/string.view.cons/assign.pass.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/std/strings/string.view/string.view.cons/assign.pass.cpp b/test/std/strings/string.view/string.view.cons/assign.pass.cpp index 478bec7e5..3307aa61d 100644 --- a/test/std/strings/string.view/string.view.cons/assign.pass.cpp +++ b/test/std/strings/string.view/string.view.cons/assign.pass.cpp @@ -33,9 +33,11 @@ bool test (T sv0) int main () { assert( test ( "1234")); +#if TEST_STD_VER >= 11 #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS assert( test (u"1234")); assert( test (U"1234")); +#endif #endif assert( test (L"1234")); -- GitLab From 9765ed0367a8346bb498b3e741751cc13ca7839c Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Fri, 13 Jul 2018 16:26:16 +0000 Subject: [PATCH 027/495] Fix a couple of 'unused variable' warnings in a vector test. NFC. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337016 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/std/containers/sequences/vector/iterators.pass.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/std/containers/sequences/vector/iterators.pass.cpp b/test/std/containers/sequences/vector/iterators.pass.cpp index a1ce2be32..33093e151 100644 --- a/test/std/containers/sequences/vector/iterators.pass.cpp +++ b/test/std/containers/sequences/vector/iterators.pass.cpp @@ -77,6 +77,8 @@ int main() typedef std::vector C; C::iterator i; C::const_iterator j; + (void) i; + (void) j; } #if TEST_STD_VER >= 11 { @@ -125,6 +127,8 @@ int main() typedef std::vector> C; C::iterator i; C::const_iterator j; + (void) i; + (void) j; } { typedef A T; -- GitLab From c005c7e34c3d22d1dba2cfe62c79f9e8be2d60de Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Fri, 13 Jul 2018 16:35:26 +0000 Subject: [PATCH 028/495] Make internal class __wrap_iter constexpr when not using libc++'s debugging mode. Introduce a new macro _LIBCPP_CONSTEXPR_IF_NODEBUG to mark this. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337019 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__config | 8 ++++ include/algorithm | 4 +- include/iterator | 110 +++++++++++++++++++++++----------------------- 3 files changed, 66 insertions(+), 56 deletions(-) diff --git a/include/__config b/include/__config index 233c2b3ab..87ba7e6e4 100644 --- a/include/__config +++ b/include/__config @@ -1023,6 +1023,14 @@ template struct __static_assert_check {}; # define _LIBCPP_EXPLICIT_MOVE(x) (x) #endif +#ifndef _LIBCPP_CONSTEXPR_IF_NODEBUG +#if !defined(_LIBCPP_DEBUG) && _LIBCPP_STD_VER >= 14 +#define _LIBCPP_CONSTEXPR_IF_NODEBUG constexpr +#else +#define _LIBCPP_CONSTEXPR_IF_NODEBUG +#endif +#endif + #ifndef _LIBCPP_HAS_NO_ASAN _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container( const void *, const void *, const void *, const void *); diff --git a/include/algorithm b/include/algorithm index a94b07bda..b8fa7e779 100644 --- a/include/algorithm +++ b/include/algorithm @@ -1708,7 +1708,7 @@ __unwrap_iter(move_iterator<_Tp*> __i) #if _LIBCPP_DEBUG_LEVEL < 2 template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1722,7 +1722,7 @@ __unwrap_iter(__wrap_iter<_Tp*> __i) #else template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG typename enable_if < is_trivially_copy_assignable<_Tp>::value, diff --git a/include/iterator b/include/iterator index 8b887db03..66592b887 100644 --- a/include/iterator +++ b/include/iterator @@ -1217,38 +1217,38 @@ make_move_iterator(_Iter __i) template class __wrap_iter; template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator==(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator<(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator!=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator>(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator>=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator<=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; #ifndef _LIBCPP_CXX03_LANG template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG auto operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG -> decltype(__x.base() - __y.base()); @@ -1260,7 +1260,7 @@ operator-(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBU #endif template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter<_Iter> operator+(typename __wrap_iter<_Iter>::difference_type, __wrap_iter<_Iter>) _NOEXCEPT_DEBUG; @@ -1272,7 +1272,7 @@ template _B2 _LIBCPP_INLINE_VISIBILITY move_backward(_B1, #if _LIBCPP_DEBUG_LEVEL < 2 template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1283,7 +1283,7 @@ __unwrap_iter(__wrap_iter<_Tp*>); #else template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1306,7 +1306,7 @@ public: private: iterator_type __i; public: - _LIBCPP_INLINE_VISIBILITY __wrap_iter() _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter() _NOEXCEPT_DEBUG #if _LIBCPP_STD_VER > 11 : __i{} #endif @@ -1315,22 +1315,23 @@ public: __get_db()->__insert_i(this); #endif } - template _LIBCPP_INLINE_VISIBILITY __wrap_iter(const __wrap_iter<_Up>& __u, - typename enable_if::value>::type* = 0) _NOEXCEPT_DEBUG - : __i(__u.base()) + template _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG + __wrap_iter(const __wrap_iter<_Up>& __u, + typename enable_if::value>::type* = 0) _NOEXCEPT_DEBUG + : __i(__u.base()) { #if _LIBCPP_DEBUG_LEVEL >= 2 __get_db()->__iterator_copy(this, &__u); #endif } #if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(const __wrap_iter& __x) : __i(__x.base()) { __get_db()->__iterator_copy(this, &__x); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator=(const __wrap_iter& __x) { if (this != &__x) @@ -1340,13 +1341,13 @@ public: } return *this; } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG ~__wrap_iter() { __get_db()->__erase_i(this); } #endif - _LIBCPP_INLINE_VISIBILITY reference operator*() const _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator*() const _NOEXCEPT_DEBUG { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), @@ -1354,7 +1355,7 @@ public: #endif return *__i; } - _LIBCPP_INLINE_VISIBILITY pointer operator->() const _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG pointer operator->() const _NOEXCEPT_DEBUG { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), @@ -1362,7 +1363,7 @@ public: #endif return (pointer)_VSTD::addressof(*__i); } - _LIBCPP_INLINE_VISIBILITY __wrap_iter& operator++() _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator++() _NOEXCEPT_DEBUG { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), @@ -1371,7 +1372,7 @@ public: ++__i; return *this; } - _LIBCPP_INLINE_VISIBILITY __wrap_iter operator++(int) _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator++(int) _NOEXCEPT_DEBUG {__wrap_iter __tmp(*this); ++(*this); return __tmp;} _LIBCPP_INLINE_VISIBILITY __wrap_iter& operator--() _NOEXCEPT_DEBUG { @@ -1382,11 +1383,11 @@ public: --__i; return *this; } - _LIBCPP_INLINE_VISIBILITY __wrap_iter operator--(int) _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator--(int) _NOEXCEPT_DEBUG {__wrap_iter __tmp(*this); --(*this); return __tmp;} - _LIBCPP_INLINE_VISIBILITY __wrap_iter operator+ (difference_type __n) const _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator+ (difference_type __n) const _NOEXCEPT_DEBUG {__wrap_iter __w(*this); __w += __n; return __w;} - _LIBCPP_INLINE_VISIBILITY __wrap_iter& operator+=(difference_type __n) _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator+=(difference_type __n) _NOEXCEPT_DEBUG { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__addable(this, __n), @@ -1395,11 +1396,11 @@ public: __i += __n; return *this; } - _LIBCPP_INLINE_VISIBILITY __wrap_iter operator- (difference_type __n) const _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator- (difference_type __n) const _NOEXCEPT_DEBUG {return *this + (-__n);} - _LIBCPP_INLINE_VISIBILITY __wrap_iter& operator-=(difference_type __n) _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator-=(difference_type __n) _NOEXCEPT_DEBUG {*this += -__n; return *this;} - _LIBCPP_INLINE_VISIBILITY reference operator[](difference_type __n) const _NOEXCEPT_DEBUG + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG reference operator[](difference_type __n) const _NOEXCEPT_DEBUG { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__subscriptable(this, __n), @@ -1408,67 +1409,68 @@ public: return __i[__n]; } - _LIBCPP_INLINE_VISIBILITY iterator_type base() const _NOEXCEPT_DEBUG {return __i;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG iterator_type base() const _NOEXCEPT_DEBUG {return __i;} private: #if _LIBCPP_DEBUG_LEVEL >= 2 - _LIBCPP_INLINE_VISIBILITY __wrap_iter(const void* __p, iterator_type __x) : __i(__x) + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(const void* __p, iterator_type __x) : __i(__x) { __get_db()->__insert_ic(this, __p); } #else - _LIBCPP_INLINE_VISIBILITY __wrap_iter(iterator_type __x) _NOEXCEPT_DEBUG : __i(__x) {} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter(iterator_type __x) _NOEXCEPT_DEBUG : __i(__x) {} #endif template friend class __wrap_iter; template friend class basic_string; template friend class _LIBCPP_TEMPLATE_VIS vector; + template friend class _LIBCPP_TEMPLATE_VIS span; template - friend + _LIBCPP_CONSTEXPR_IF_NODEBUG friend bool operator==(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; template - friend + _LIBCPP_CONSTEXPR_IF_NODEBUG friend bool operator<(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; template - friend + _LIBCPP_CONSTEXPR_IF_NODEBUG friend bool operator!=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; template - friend + _LIBCPP_CONSTEXPR_IF_NODEBUG friend bool operator>(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; template - friend + _LIBCPP_CONSTEXPR_IF_NODEBUG friend bool operator>=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; template - friend + _LIBCPP_CONSTEXPR_IF_NODEBUG friend bool operator<=(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; #ifndef _LIBCPP_CXX03_LANG template - friend + _LIBCPP_CONSTEXPR_IF_NODEBUG friend auto operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG -> decltype(__x.base() - __y.base()); #else template - friend + _LIBCPP_CONSTEXPR_IF_NODEBUG friend typename __wrap_iter<_Iter1>::difference_type operator-(const __wrap_iter<_Iter1>&, const __wrap_iter<_Iter2>&) _NOEXCEPT_DEBUG; #endif template - friend + _LIBCPP_CONSTEXPR_IF_NODEBUG friend __wrap_iter<_Iter1> operator+(typename __wrap_iter<_Iter1>::difference_type, __wrap_iter<_Iter1>) _NOEXCEPT_DEBUG; @@ -1479,7 +1481,7 @@ private: #if _LIBCPP_DEBUG_LEVEL < 2 template - friend + _LIBCPP_CONSTEXPR_IF_NODEBUG friend typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1488,7 +1490,7 @@ private: __unwrap_iter(__wrap_iter<_Tp*>); #else template - inline _LIBCPP_INLINE_VISIBILITY + inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG typename enable_if < is_trivially_copy_assignable<_Tp>::value, @@ -1499,7 +1501,7 @@ private: }; template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG { @@ -1507,7 +1509,7 @@ operator==(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEX } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG { @@ -1519,7 +1521,7 @@ operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXC } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG { @@ -1527,7 +1529,7 @@ operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEX } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG { @@ -1535,7 +1537,7 @@ operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXC } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG { @@ -1543,7 +1545,7 @@ operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEX } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG { @@ -1551,7 +1553,7 @@ operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEX } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT_DEBUG { @@ -1559,7 +1561,7 @@ operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEX } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT_DEBUG { @@ -1567,7 +1569,7 @@ operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXC } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT_DEBUG { @@ -1575,7 +1577,7 @@ operator>=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEX } template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG bool operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT_DEBUG { @@ -1584,7 +1586,7 @@ operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEX #ifndef _LIBCPP_CXX03_LANG template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG auto operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG -> decltype(__x.base() - __y.base()) @@ -1597,7 +1599,7 @@ operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXC } #else template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG typename __wrap_iter<_Iter1>::difference_type operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT_DEBUG { @@ -1610,7 +1612,7 @@ operator-(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXC #endif template -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter<_Iter> operator+(typename __wrap_iter<_Iter>::difference_type __n, __wrap_iter<_Iter> __x) _NOEXCEPT_DEBUG -- GitLab From e585baf371a3483e95c88ab34bd1bbf1683792b1 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Fri, 13 Jul 2018 17:24:59 +0000 Subject: [PATCH 029/495] Shot in the dark to fix gcc 4.9 / c++11 build git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337027 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/__config b/include/__config index 87ba7e6e4..65df5ddb9 100644 --- a/include/__config +++ b/include/__config @@ -1024,10 +1024,10 @@ template struct __static_assert_check {}; #endif #ifndef _LIBCPP_CONSTEXPR_IF_NODEBUG -#if !defined(_LIBCPP_DEBUG) && _LIBCPP_STD_VER >= 14 -#define _LIBCPP_CONSTEXPR_IF_NODEBUG constexpr -#else +#if defined(_LIBCPP_DEBUG) || _LIBCPP_HAS_NO_CXX14_CONSTEXPR #define _LIBCPP_CONSTEXPR_IF_NODEBUG +#else +#define _LIBCPP_CONSTEXPR_IF_NODEBUG constexpr #endif #endif -- GitLab From 1548d77c823a8256a92f4238cd5edb97b98ee5ca Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Fri, 13 Jul 2018 17:31:36 +0000 Subject: [PATCH 030/495] wrap _LIBCPP_HAS_NO_CXX14_CONSTEXPR in defined(...) git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337028 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/__config b/include/__config index 65df5ddb9..49b8fd79f 100644 --- a/include/__config +++ b/include/__config @@ -1024,7 +1024,7 @@ template struct __static_assert_check {}; #endif #ifndef _LIBCPP_CONSTEXPR_IF_NODEBUG -#if defined(_LIBCPP_DEBUG) || _LIBCPP_HAS_NO_CXX14_CONSTEXPR +#if defined(_LIBCPP_DEBUG) || defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) #define _LIBCPP_CONSTEXPR_IF_NODEBUG #else #define _LIBCPP_CONSTEXPR_IF_NODEBUG constexpr -- GitLab From d7d3d8bc1830c5f0e9e3971cf92d70b634b61c83 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Sat, 14 Jul 2018 03:06:11 +0000 Subject: [PATCH 031/495] Mark one more __wrap_iter operation as constexpr. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337085 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/iterator | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/iterator b/include/iterator index 66592b887..9415e0b83 100644 --- a/include/iterator +++ b/include/iterator @@ -1374,7 +1374,8 @@ public: } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter operator++(int) _NOEXCEPT_DEBUG {__wrap_iter __tmp(*this); ++(*this); return __tmp;} - _LIBCPP_INLINE_VISIBILITY __wrap_iter& operator--() _NOEXCEPT_DEBUG + + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_IF_NODEBUG __wrap_iter& operator--() _NOEXCEPT_DEBUG { #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_ASSERT(__get_const_db()->__decrementable(this), -- GitLab From 0d0b9729271b3ef6c4ac9dfcee3c8c9f4aa79ec9 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Sat, 14 Jul 2018 04:15:19 +0000 Subject: [PATCH 032/495] Mark __equal_to 's operations as constexpr. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337087 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/algorithm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/algorithm b/include/algorithm index b8fa7e779..90f1d246c 100644 --- a/include/algorithm +++ b/include/algorithm @@ -671,10 +671,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD template struct __equal_to { - _LIBCPP_INLINE_VISIBILITY bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;} - _LIBCPP_INLINE_VISIBILITY bool operator()(const _T1& __x, const _T2& __y) const {return __x == __y;} - _LIBCPP_INLINE_VISIBILITY bool operator()(const _T2& __x, const _T1& __y) const {return __x == __y;} - _LIBCPP_INLINE_VISIBILITY bool operator()(const _T2& __x, const _T2& __y) const {return __x == __y;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T1& __x, const _T2& __y) const {return __x == __y;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T2& __x, const _T1& __y) const {return __x == __y;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _T2& __x, const _T2& __y) const {return __x == __y;} }; template -- GitLab From a40a6b3f6e4b186ba7b510526bc24679e6556621 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Sun, 15 Jul 2018 04:09:35 +0000 Subject: [PATCH 033/495] [CMake] Use correct variable as header install prefix This variable is already set in CMakeLists.txt but it wasn't used which means that the headers get installed into a wrong location when the per target runtime directory option is being used. Differential Revision: https://reviews.llvm.org/D49345 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337118 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index be0e10d50..e44ff3ef3 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -239,7 +239,7 @@ if (LIBCXX_INSTALL_HEADERS) foreach(file ${files}) get_filename_component(dir ${file} DIRECTORY) install(FILES ${file} - DESTINATION ${LIBCXX_INSTALL_PATH}include/c++/v1/${dir} + DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1/${dir} COMPONENT cxx-headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) @@ -248,7 +248,7 @@ if (LIBCXX_INSTALL_HEADERS) if (LIBCXX_NEEDS_SITE_CONFIG) # Install the generated header as __config. install(FILES ${LIBCXX_BINARY_DIR}/__generated_config - DESTINATION ${LIBCXX_INSTALL_PATH}include/c++/v1 + DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1 PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ RENAME __config COMPONENT cxx-headers) -- GitLab From 6e089f8b100bb5c118879cf6e1ca935cb89fa259 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 16 Jul 2018 20:01:59 +0000 Subject: [PATCH 034/495] Fix PR38160 - init_priority attribute not supported by GCC on Apple. This patch guards the use of __attribute__((init_priority(101))) within memory_resource.cpp when building with compilers that don't support it. Specifically GCC on Apple platforms, and MSVC. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337205 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/memory_resource.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/experimental/memory_resource.cpp b/src/experimental/memory_resource.cpp index a6eca3743..a3b64cc8b 100644 --- a/src/experimental/memory_resource.cpp +++ b/src/experimental/memory_resource.cpp @@ -68,12 +68,23 @@ union ResourceInitHelper { _LIBCPP_CONSTEXPR_AFTER_CXX11 ResourceInitHelper() : resources() {} ~ResourceInitHelper() {} }; + +// Detect if the init_priority attribute is supported. +#if (defined(_LIBCPP_COMPILER_GCC) && defined(__APPLE__)) \ + || defined(_LIBCPP_COMPILER_MSVC) +// GCC on Apple doesn't support the init priority attribute, +// and MSVC doesn't support any GCC attributes. +# define _LIBCPP_INIT_PRIORITY_MAX +#else +# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((init_priority(101))) +#endif + // When compiled in C++14 this initialization should be a constant expression. // Only in C++11 is "init_priority" needed to ensure initialization order. #if _LIBCPP_STD_VER > 11 _LIBCPP_SAFE_STATIC #endif -ResourceInitHelper res_init __attribute__((init_priority (101))); +ResourceInitHelper res_init _LIBCPP_INIT_PRIORITY_MAX; } // end namespace -- GitLab From ffbb91bb640b1b0425a91aa70e2a6a2e0f7244e0 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Tue, 17 Jul 2018 05:48:48 +0000 Subject: [PATCH 035/495] Address "always inline function is not always inlinable" warning with GCC. When an always_inline function is used prior to the functions definition, the compiler may not be able to inline it as requested by the attribute. GCC flags the `basic_string(CharT const*)` function as one such example. This patch supresses the warning, and the problem, by moving the definition of the string constructor to the inline declaration. This ensures the body is available when it is first ODR used. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337235 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/string | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/include/string b/include/string index 96d36f4f7..162e54058 100644 --- a/include/string +++ b/include/string @@ -807,8 +807,14 @@ public: #endif // _LIBCPP_CXX03_LANG template ::value, nullptr_t>::type> - _LIBCPP_INLINE_VISIBILITY - basic_string(const _CharT* __s); + _LIBCPP_INLINE_VISIBILITY + basic_string(const _CharT* __s) { + _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr"); + __init(__s, traits_type::length(__s)); +# if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +# endif + } template ::value, nullptr_t>::type> _LIBCPP_INLINE_VISIBILITY @@ -1773,17 +1779,6 @@ basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_ty traits_type::assign(__p[__sz], value_type()); } -template -template -basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s) -{ - _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr"); - __init(__s, traits_type::length(__s)); -#if _LIBCPP_DEBUG_LEVEL >= 2 - __get_db()->__insert_c(this); -#endif -} - template template basic_string<_CharT, _Traits, _Allocator>::basic_string(const _CharT* __s, const _Allocator& __a) -- GitLab From f1f54dc0fbe3da97487c96f3e183fb9378822d5e Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 18 Jul 2018 17:37:51 +0000 Subject: [PATCH 036/495] Update the synopsis for for C++20. No functional change. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337406 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/chrono | 492 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 492 insertions(+) diff --git a/include/chrono b/include/chrono index 809f773b6..f6a6f4b24 100644 --- a/include/chrono +++ b/include/chrono @@ -147,6 +147,11 @@ template namespace chrono { + +template struct is_clock; // C++20 +template inline constexpr bool is_clock_v = is_clock::value; // C++20 + + // duration arithmetic template constexpr @@ -204,6 +209,8 @@ template template constexpr ToDuration round(const duration& d); // C++17 +// duration I/O is elsewhere + // time_point arithmetic (all constexpr in C++14) template time_point>::type> @@ -251,6 +258,7 @@ template template constexpr duration abs(duration d); // C++17 + // Clocks class system_clock @@ -267,6 +275,28 @@ public: static time_point from_time_t(time_t __t) noexcept; }; +template + using sys_time = time_point; // C++20 +using sys_seconds = sys_time; // C++20 +using sys_days = sys_time; // C++20 + +class utc_clock; // C++20 + +template + using utc_time = time_point; // C++20 +using utc_seconds = utc_time; // C++20 + +class tai_clock; // C++20 + +template + using tai_time = time_point; // C++20 +using tai_seconds = tai_time; // C++20 + +class file_clock; // C++20 + +template + using file_time = time_point; // C++20 + class steady_clock { public: @@ -281,8 +311,466 @@ public: typedef steady_clock high_resolution_clock; +// 25.7.8, local time // C++20 +struct local_t {}; +template + using local_time = time_point; +using local_seconds = local_time; +using local_days = local_time; + +// 25.7.9, time_point conversions template // C++20 +struct clock_time_conversion; + +template + auto clock_cast(const time_point& t); + +// 25.8.2, class last_spec // C++20 +struct last_spec; + +// 25.8.3, class day // C++20 + +class day; +constexpr bool operator==(const day& x, const day& y) noexcept; +constexpr bool operator!=(const day& x, const day& y) noexcept; +constexpr bool operator< (const day& x, const day& y) noexcept; +constexpr bool operator> (const day& x, const day& y) noexcept; +constexpr bool operator<=(const day& x, const day& y) noexcept; +constexpr bool operator>=(const day& x, const day& y) noexcept; +constexpr day operator+(const day& x, const days& y) noexcept; +constexpr day operator+(const days& x, const day& y) noexcept; +constexpr day operator-(const day& x, const days& y) noexcept; +constexpr days operator-(const day& x, const day& y) noexcept; + +// 25.8.4, class month // C++20 +class month; +constexpr bool operator==(const month& x, const month& y) noexcept; +constexpr bool operator!=(const month& x, const month& y) noexcept; +constexpr bool operator< (const month& x, const month& y) noexcept; +constexpr bool operator> (const month& x, const month& y) noexcept; +constexpr bool operator<=(const month& x, const month& y) noexcept; +constexpr bool operator>=(const month& x, const month& y) noexcept; +constexpr month operator+(const month& x, const months& y) noexcept; +constexpr month operator+(const months& x, const month& y) noexcept; +constexpr month operator-(const month& x, const months& y) noexcept; +constexpr months operator-(const month& x, const month& y) noexcept; + +// 25.8.5, class year // C++20 +class year; +constexpr bool operator==(const year& x, const year& y) noexcept; +constexpr bool operator!=(const year& x, const year& y) noexcept; +constexpr bool operator< (const year& x, const year& y) noexcept; +constexpr bool operator> (const year& x, const year& y) noexcept; +constexpr bool operator<=(const year& x, const year& y) noexcept; +constexpr bool operator>=(const year& x, const year& y) noexcept; +constexpr year operator+(const year& x, const years& y) noexcept; +constexpr year operator+(const years& x, const year& y) noexcept; +constexpr year operator-(const year& x, const years& y) noexcept; +constexpr years operator-(const year& x, const year& y) noexcept; + +// 25.8.6, class weekday // C++20 +class weekday; + +constexpr bool operator==(const weekday& x, const weekday& y) noexcept; +constexpr bool operator!=(const weekday& x, const weekday& y) noexcept; +constexpr weekday operator+(const weekday& x, const days& y) noexcept; +constexpr weekday operator+(const days& x, const weekday& y) noexcept; +constexpr weekday operator-(const weekday& x, const days& y) noexcept; +constexpr days operator-(const weekday& x, const weekday& y) noexcept; + +// 25.8.7, class weekday_indexed // C++20 + +class weekday_indexed; +constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; +constexpr bool operator!=(const weekday_indexed& x, const weekday_indexed& y) noexcept; + +// 25.8.8, class weekday_last // C++20 +class weekday_last; + +constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; +constexpr bool operator!=(const weekday_last& x, const weekday_last& y) noexcept; + +// 25.8.9, class month_day // C++20 +class month_day; + +constexpr bool operator==(const month_day& x, const month_day& y) noexcept; +constexpr bool operator!=(const month_day& x, const month_day& y) noexcept; +constexpr bool operator< (const month_day& x, const month_day& y) noexcept; +constexpr bool operator> (const month_day& x, const month_day& y) noexcept; +constexpr bool operator<=(const month_day& x, const month_day& y) noexcept; +constexpr bool operator>=(const month_day& x, const month_day& y) noexcept; + + +// 25.8.10, class month_day_last // C++20 +class month_day_last; + +constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; +constexpr bool operator!=(const month_day_last& x, const month_day_last& y) noexcept; +constexpr bool operator< (const month_day_last& x, const month_day_last& y) noexcept; +constexpr bool operator> (const month_day_last& x, const month_day_last& y) noexcept; +constexpr bool operator<=(const month_day_last& x, const month_day_last& y) noexcept; +constexpr bool operator>=(const month_day_last& x, const month_day_last& y) noexcept; + +// 25.8.11, class month_weekday // C++20 +class month_weekday; + +constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; +constexpr bool operator!=(const month_weekday& x, const month_weekday& y) noexcept; + +// 25.8.12, class month_weekday_last // C++20 +class month_weekday_last; + +constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; +constexpr bool operator!=(const month_weekday_last& x, const month_weekday_last& y) noexcept; + + +// 25.8.13, class year_month // C++20 +class year_month; + +constexpr bool operator==(const year_month& x, const year_month& y) noexcept; +constexpr bool operator!=(const year_month& x, const year_month& y) noexcept; +constexpr bool operator< (const year_month& x, const year_month& y) noexcept; +constexpr bool operator> (const year_month& x, const year_month& y) noexcept; +constexpr bool operator<=(const year_month& x, const year_month& y) noexcept; +constexpr bool operator>=(const year_month& x, const year_month& y) noexcept; + +constexpr year_month operator+(const year_month& ym, const months& dm) noexcept; +constexpr year_month operator+(const months& dm, const year_month& ym) noexcept; +constexpr year_month operator-(const year_month& ym, const months& dm) noexcept; +constexpr months operator-(const year_month& x, const year_month& y) noexcept; +constexpr year_month operator+(const year_month& ym, const years& dy) noexcept; +constexpr year_month operator+(const years& dy, const year_month& ym) noexcept; +constexpr year_month operator-(const year_month& ym, const years& dy) noexcept; + +// 25.8.14, class year_month_day class // C++20 +year_month_day; + +constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept; +constexpr bool operator!=(const year_month_day& x, const year_month_day& y) noexcept; +constexpr bool operator< (const year_month_day& x, const year_month_day& y) noexcept; +constexpr bool operator> (const year_month_day& x, const year_month_day& y) noexcept; +constexpr bool operator<=(const year_month_day& x, const year_month_day& y) noexcept; +constexpr bool operator>=(const year_month_day& x, const year_month_day& y) noexcept; + +constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept; +constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept; +constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept; +constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept; +constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept; +constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept; + + +// 25.8.15, class year_month_day_last // C++20 +class year_month_day_last; + +constexpr bool operator==(const year_month_day_last& x, + const year_month_day_last& y) noexcept; +constexpr bool operator!=(const year_month_day_last& x, + const year_month_day_last& y) noexcept; +constexpr bool operator< (const year_month_day_last& x, + const year_month_day_last& y) noexcept; +constexpr bool operator> (const year_month_day_last& x, + const year_month_day_last& y) noexcept; +constexpr bool operator<=(const year_month_day_last& x, + const year_month_day_last& y) noexcept; +constexpr bool operator>=(const year_month_day_last& x, + const year_month_day_last& y) noexcept; + +constexpr year_month_day_last + operator+(const year_month_day_last& ymdl, const months& dm) noexcept; +constexpr year_month_day_last + operator+(const months& dm, const year_month_day_last& ymdl) noexcept; +constexpr year_month_day_last + operator+(const year_month_day_last& ymdl, const years& dy) noexcept; +constexpr year_month_day_last + operator+(const years& dy, const year_month_day_last& ymdl) noexcept; +constexpr year_month_day_last + operator-(const year_month_day_last& ymdl, const months& dm) noexcept; +constexpr year_month_day_last + operator-(const year_month_day_last& ymdl, const years& dy) noexcept; + +// 25.8.16, class year_month_weekday // C++20 +class year_month_weekday; + +constexpr bool operator==(const year_month_weekday& x, + const year_month_weekday& y) noexcept; +constexpr bool operator!=(const year_month_weekday& x, + const year_month_weekday& y) noexcept; + +constexpr year_month_weekday + operator+(const year_month_weekday& ymwd, const months& dm) noexcept; +constexpr year_month_weekday + operator+(const months& dm, const year_month_weekday& ymwd) noexcept; +constexpr year_month_weekday + operator+(const year_month_weekday& ymwd, const years& dy) noexcept; +constexpr year_month_weekday + operator+(const years& dy, const year_month_weekday& ymwd) noexcept; +constexpr year_month_weekday + operator-(const year_month_weekday& ymwd, const months& dm) noexcept; +constexpr year_month_weekday + operator-(const year_month_weekday& ymwd, const years& dy) noexcept; + +// 25.8.17, class year_month_weekday_last // C++20 +class year_month_weekday_last; + +constexpr bool operator==(const year_month_weekday_last& x, + const year_month_weekday_last& y) noexcept; +constexpr bool operator!=(const year_month_weekday_last& x, + const year_month_weekday_last& y) noexcept; +constexpr year_month_weekday_last + operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept; +constexpr year_month_weekday_last + operator+(const months& dm, const year_month_weekday_last& ymwdl) noexcept; +constexpr year_month_weekday_last + operator+(const year_month_weekday_last& ymwdl, const years& dy) noexcept; +constexpr year_month_weekday_last + operator+(const years& dy, const year_month_weekday_last& ymwdl) noexcept; +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; +constexpr year_month + operator/(const year& y, int m) noexcept; +constexpr month_day + operator/(const month& m, const day& d) noexcept; +constexpr month_day + operator/(const month& m, int d) noexcept; +constexpr month_day + operator/(int m, const day& d) noexcept; +constexpr month_day + operator/(const day& d, const month& m) noexcept; +constexpr month_day + operator/(const day& d, int m) noexcept; +constexpr month_day_last + operator/(const month& m, last_spec) noexcept; +constexpr month_day_last + operator/(int m, last_spec) noexcept; +constexpr month_day_last + operator/(last_spec, const month& m) noexcept; +constexpr month_day_last + operator/(last_spec, int m) noexcept; +constexpr month_weekday + operator/(const month& m, const weekday_indexed& wdi) noexcept; +constexpr month_weekday + operator/(int m, const weekday_indexed& wdi) noexcept; +constexpr month_weekday + operator/(const weekday_indexed& wdi, const month& m) noexcept; +constexpr month_weekday + operator/(const weekday_indexed& wdi, int m) noexcept; +constexpr month_weekday_last + operator/(const month& m, const weekday_last& wdl) noexcept; +constexpr month_weekday_last + operator/(int m, const weekday_last& wdl) noexcept; +constexpr month_weekday_last + operator/(const weekday_last& wdl, const month& m) noexcept; +constexpr month_weekday_last + operator/(const weekday_last& wdl, int m) noexcept; +constexpr year_month_day + operator/(const year_month& ym, const day& d) noexcept; +constexpr year_month_day + operator/(const year_month& ym, int d) noexcept; +constexpr year_month_day + operator/(const year& y, const month_day& md) noexcept; +constexpr year_month_day + operator/(int y, const month_day& md) noexcept; +constexpr year_month_day + operator/(const month_day& md, const year& y) noexcept; +constexpr year_month_day + operator/(const month_day& md, int y) noexcept; +constexpr year_month_day_last + operator/(const year_month& ym, last_spec) noexcept; +constexpr year_month_day_last + operator/(const year& y, const month_day_last& mdl) noexcept; +constexpr year_month_day_last + operator/(int y, const month_day_last& mdl) noexcept; +constexpr year_month_day_last + operator/(const month_day_last& mdl, const year& y) noexcept; +constexpr year_month_day_last + operator/(const month_day_last& mdl, int y) noexcept; +constexpr year_month_weekday + operator/(const year_month& ym, const weekday_indexed& wdi) noexcept; +constexpr year_month_weekday + operator/(const year& y, const month_weekday& mwd) noexcept; +constexpr year_month_weekday + operator/(int y, const month_weekday& mwd) noexcept; +constexpr year_month_weekday + operator/(const month_weekday& mwd, const year& y) noexcept; +constexpr year_month_weekday + operator/(const month_weekday& mwd, int y) noexcept; +constexpr year_month_weekday_last + operator/(const year_month& ym, const weekday_last& wdl) noexcept; +constexpr year_month_weekday_last + operator/(const year& y, const month_weekday_last& mwdl) noexcept; +constexpr year_month_weekday_last + operator/(int y, const month_weekday_last& mwdl) noexcept; +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; + +// 25.9, class template time_of_day // C++20 +template class time_of_day; + +template<> class time_of_day; +template<> class time_of_day; +template<> class time_of_day; +template class time_of_day>; + +// 25.10.2, time zone database // C++20 +struct tzdb; +class tzdb_list; + +// 25.10.2.3, time zone database access // C++20 +const tzdb& get_tzdb(); +tzdb_list& get_tzdb_list(); +const time_zone* locate_zone(string_view tz_name); +const time_zone* current_zone(); + +// 25.10.2.4, remote time zone database support // C++20 +const tzdb& reload_tzdb(); +string remote_version(); + +// 25.10.3, exception classes // C++20 +class nonexistent_local_time; +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; +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; +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 struct zoned_traits; + +// 25.10.7, class template zoned_time // C++20 +template class zoned_time; +using zoned_seconds = zoned_time; + +template + bool operator==(const zoned_time& x, + const zoned_time& y); +template + bool operator!=(const zoned_time& x, + const zoned_time& y); + +// 25.10.8, leap second support // C++20 +class leap; + +bool operator==(const leap& x, const leap& y); +bool operator!=(const leap& x, const leap& y); +bool operator< (const leap& x, const leap& y); +bool operator> (const leap& x, const leap& y); +bool operator<=(const leap& x, const leap& y); +bool operator>=(const leap& x, const leap& y); +template + bool operator==(const leap& x, const sys_time& y); +template + bool operator==(const sys_time& x, const leap& y); +template + bool operator!=(const leap& x, const sys_time& y); +template + bool operator!=(const sys_time& x, const leap& y); +template + bool operator< (const leap& x, const sys_time& y); +template + bool operator< (const sys_time& x, const leap& y); +template + bool operator> (const leap& x, const sys_time& y); +template + bool operator> (const sys_time& x, const leap& y); +template + bool operator<=(const leap& x, const sys_time& y); +template + bool operator<=(const sys_time& x, const leap& y); +template + bool operator>=(const leap& x, const sys_time& y); +template + bool operator>=(const sys_time& x, const leap& y); + +// 25.10.9, class link // C++20 +class link; +bool operator==(const link& x, const link& y); +bool operator!=(const link& x, const link& y); +bool operator< (const link& x, const link& y); +bool operator> (const link& x, const link& y); +bool operator<=(const link& x, const link& y); +bool operator>=(const link& x, const link& y); + +// 25.11, formatting // C++20 +template + basic_string + format(const charT* fmt, const Streamable& s); + +template + basic_string + format(const locale& loc, const charT* fmt, const Streamable& s); + +template + basic_string + format(const basic_string& fmt, const Streamable& s); + +template + basic_string + format(const locale& loc, const basic_string& fmt, + const Streamable& s); + +// 25.12, parsing // C++20 +template +unspecified + parse(const basic_string& format, Parsable& tp); + +template +unspecified + parse(const basic_string& format, Parsable& tp, + basic_string& abbrev); + +template +unspecified + parse(const basic_string& format, Parsable& tp, + minutes& offset); + +template +unspecified + parse(const basic_string& format, Parsable& tp, + basic_string& abbrev, minutes& offset); + +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 +inline constexpr chrono::weekday Wednesday{3}; // C++20 +inline constexpr chrono::weekday Thursday{4}; // C++20 +inline constexpr chrono::weekday Friday{5}; // C++20 +inline constexpr chrono::weekday Saturday{6}; // C++20 + +inline constexpr chrono::month January{1}; // C++20 +inline constexpr chrono::month February{2}; // C++20 +inline constexpr chrono::month March{3}; // C++20 +inline constexpr chrono::month April{4}; // C++20 +inline constexpr chrono::month May{5}; // C++20 +inline constexpr chrono::month June{6}; // C++20 +inline constexpr chrono::month July{7}; // C++20 +inline constexpr chrono::month August{8}; // C++20 +inline constexpr chrono::month September{9}; // C++20 +inline constexpr chrono::month October{10}; // C++20 +inline constexpr chrono::month November{11}; // C++20 +inline constexpr chrono::month December{12}; // C++20 } // chrono +inline namespace literals { + inline namespace chrono_literals { constexpr chrono::hours operator ""h(unsigned long long); // C++14 constexpr chrono::duration> operator ""h(long double); // C++14 constexpr chrono::minutes operator ""min(unsigned long long); // C++14 @@ -295,6 +783,10 @@ constexpr chrono::microseconds operator ""us(unsigned l constexpr chrono::duration operator ""us(long double); // C++14 constexpr chrono::nanoseconds operator ""ns(unsigned long long); // C++14 constexpr chrono::duration operator ""ns(long double); // C++14 +constexpr chrono::day operator ""d(unsigned long long d) noexcept; // C++20 +constexpr chrono::year operator ""y(unsigned long long y) noexcept; // C++20 +} // chrono_literals +} // literals } // std */ -- GitLab From c69e1a06154ae84c564588ecf0a2d7c1018f4483 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Thu, 19 Jul 2018 18:02:50 +0000 Subject: [PATCH 037/495] [libc++] Allow running ABI list tests with different ABI versions Summary: Currently, the ABI list test only works for ABI version 1. This commit allows running the ABI list test with ABI version 2. It also adds an ABI list file for ABI v2 on Mac OS X. Reviewers: EricWF Subscribers: mgorny, christof, dexonsmith, llvm-commits, mclow.lists Differential Revision: https://reviews.llvm.org/D49509 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337477 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/abi/CMakeLists.txt | 24 +- ...abilist => x86_64-apple-darwin.v1.abilist} | 0 lib/abi/x86_64-apple-darwin.v2.abilist | 2418 +++++++++++++++++ ...st => x86_64-unknown-linux-gnu.v1.abilist} | 0 4 files changed, 2425 insertions(+), 17 deletions(-) rename lib/abi/{x86_64-apple-darwin.abilist => x86_64-apple-darwin.v1.abilist} (100%) create mode 100644 lib/abi/x86_64-apple-darwin.v2.abilist rename lib/abi/{x86_64-unknown-linux-gnu.abilist => x86_64-unknown-linux-gnu.v1.abilist} (100%) diff --git a/lib/abi/CMakeLists.txt b/lib/abi/CMakeLists.txt index 6cb237e9e..e42e96173 100644 --- a/lib/abi/CMakeLists.txt +++ b/lib/abi/CMakeLists.txt @@ -8,29 +8,19 @@ endif() # Detect if we are building in the same configuration used to generate # the abilist files. -if (DEFINED GENERIC_TARGET_TRIPLE - AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/${GENERIC_TARGET_TRIPLE}.abilist" +set(ABILIST_FILE "${CMAKE_CURRENT_LIST_DIR}/${GENERIC_TARGET_TRIPLE}.v${LIBCXX_ABI_VERSION}.abilist") +set(SYMDIFF_EXE "${LIBCXX_SOURCE_DIR}/utils/sym_diff.py") +if (EXISTS "${ABILIST_FILE}" AND TARGET cxx_shared AND ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi" OR (APPLE AND "${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "default")) - AND NOT LIBCXX_ABI_UNSTABLE - AND LIBCXX_ABI_VERSION EQUAL "1") - set(LIBCXX_HAS_ABILIST_CONFIGURATION 1 CACHE INTERNAL "") -else() - if (NOT DEFINED LIBCXX_HAS_ABILIST_CONFIGURATION) - message(STATUS "libc++ configuration differs from the abilist configuration. " - "check-cxx-abilist target is not supported") - endif() - set(LIBCXX_HAS_ABILIST_CONFIGURATION 0 CACHE INTERNAL "") -endif() - - -if (LIBCXX_HAS_ABILIST_CONFIGURATION) - set(ABILIST_FILE "${CMAKE_CURRENT_LIST_DIR}/${GENERIC_TARGET_TRIPLE}.abilist") - set(SYMDIFF_EXE "${LIBCXX_SOURCE_DIR}/utils/sym_diff.py") + AND NOT LIBCXX_ABI_UNSTABLE) add_custom_target(check-cxx-abilist ${SYMDIFF_EXE} --only-stdlib-symbols --strict ${ABILIST_FILE} $ DEPENDS cxx_shared COMMENT "Testing ABI compatibility...") +else() + message(STATUS "there is no pre-generated ABI list for the requested libc++ configuration. " + "check-cxx-abilist target is not supported") endif() diff --git a/lib/abi/x86_64-apple-darwin.abilist b/lib/abi/x86_64-apple-darwin.v1.abilist similarity index 100% rename from lib/abi/x86_64-apple-darwin.abilist rename to lib/abi/x86_64-apple-darwin.v1.abilist diff --git a/lib/abi/x86_64-apple-darwin.v2.abilist b/lib/abi/x86_64-apple-darwin.v2.abilist new file mode 100644 index 000000000..05255a657 --- /dev/null +++ b/lib/abi/x86_64-apple-darwin.v2.abilist @@ -0,0 +1,2418 @@ +{'type': 'U', 'is_defined': False, 'name': '__ZNKSt10bad_typeid4whatEv'} +{'type': 'I', 'is_defined': True, 'name': '__ZNKSt10bad_typeid4whatEv'} +{'type': 'U', 'is_defined': False, 'name': '__ZNKSt11logic_error4whatEv'} +{'type': 'I', 'is_defined': True, 'name': '__ZNKSt11logic_error4whatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt12bad_any_cast4whatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt12experimental15fundamentals_v112bad_any_cast4whatEv'} +{'type': 'U', 'is_defined': False, 'name': '__ZNKSt13bad_exception4whatEv'} +{'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'} +{'type': 'U', 'is_defined': False, 'name': '__ZNKSt20bad_array_new_length4whatEv'} +{'type': 'I', 'is_defined': True, 'name': '__ZNKSt20bad_array_new_length4whatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210__time_put8__do_putEPcRS1_PK2tmcc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210__time_put8__do_putEPwRS1_PK2tmcc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210error_code7messageEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb0EE11do_groupingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb0EE13do_neg_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb0EE13do_pos_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb0EE14do_curr_symbolEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb0EE14do_frac_digitsEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb0EE16do_decimal_pointEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb0EE16do_negative_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb0EE16do_positive_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb0EE16do_thousands_sepEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb1EE11do_groupingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb1EE13do_neg_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb1EE13do_pos_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb1EE14do_curr_symbolEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb1EE14do_frac_digitsEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb1EE16do_decimal_pointEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb1EE16do_negative_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb1EE16do_positive_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIcLb1EE16do_thousands_sepEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb0EE11do_groupingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb0EE13do_neg_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb0EE13do_pos_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb0EE14do_curr_symbolEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb0EE14do_frac_digitsEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb0EE16do_decimal_pointEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb0EE16do_negative_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb0EE16do_positive_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb0EE16do_thousands_sepEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb1EE11do_groupingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb1EE13do_neg_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb1EE13do_pos_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb1EE14do_curr_symbolEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb1EE14do_frac_digitsEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb1EE16do_decimal_pointEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb1EE16do_negative_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb1EE16do_positive_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__210moneypunctIwLb1EE16do_thousands_sepEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__211__libcpp_db15__decrementableEPKv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__211__libcpp_db15__find_c_from_iEPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__211__libcpp_db15__subscriptableEPKvl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__211__libcpp_db17__dereferenceableEPKv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__211__libcpp_db17__find_c_and_lockEPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__211__libcpp_db22__less_than_comparableEPKvS2_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__211__libcpp_db6unlockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__211__libcpp_db8__find_cEPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__211__libcpp_db9__addableEPKvl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212bad_weak_ptr4whatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE12find_last_ofEPKcmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE13find_first_ofEPKcmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE16find_last_not_ofEPKcmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE17find_first_not_ofEPKcmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE2atEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4copyEPcmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4findEPKcmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4findEcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5rfindEPKcmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5rfindEcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7compareEmmRKS5_mm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE12find_last_ofEPKwmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE13find_first_ofEPKwmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE16find_last_not_ofEPKwmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE17find_first_not_ofEPKwmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE2atEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4copyEPwmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4findEPKwmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4findEwm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE5rfindEPKwmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE5rfindEwm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEmmPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEmmPKwm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7compareEmmRKS5_mm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIcE10do_tolowerEPcPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIcE10do_tolowerEc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIcE10do_toupperEPcPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIcE10do_toupperEc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE10do_scan_isEjPKwS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE10do_tolowerEPwPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE10do_tolowerEw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE10do_toupperEPwPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE10do_toupperEw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE11do_scan_notEjPKwS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE5do_isEPKwS3_Pj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE5do_isEjw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE8do_widenEPKcS3_Pw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE8do_widenEc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE9do_narrowEPKwS3_cPc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212ctype_bynameIwE9do_narrowEwc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__212strstreambuf6pcountEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__213random_device7entropyEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDiE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDiE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDiE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDiE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDiE5do_inER11__mbstate_tPKcS5_RS5_PDiS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDiE6do_outER11__mbstate_tPKDiS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDiE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDsE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDsE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDsE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDsE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDsE5do_inER11__mbstate_tPKcS5_RS5_PDsS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDsE6do_outER11__mbstate_tPKDsS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IDsE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IwE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IwE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IwE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IwE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IwE5do_inER11__mbstate_tPKcS5_RS5_PwS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IwE6do_outER11__mbstate_tPKwS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214__codecvt_utf8IwE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214collate_bynameIcE10do_compareEPKcS3_S3_S3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214collate_bynameIcE12do_transformEPKcS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214collate_bynameIwE10do_compareEPKwS3_S3_S3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214collate_bynameIwE12do_transformEPKwS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214error_category10equivalentERKNS_10error_codeEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214error_category10equivalentEiRKNS_15error_conditionE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__214error_category23default_error_conditionEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb0EE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb0EE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb0EE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb0EE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb0EE5do_inER11__mbstate_tPKcS5_RS5_PDiS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb0EE6do_outER11__mbstate_tPKDiS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb0EE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb1EE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb1EE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb1EE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb1EE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb1EE5do_inER11__mbstate_tPKcS5_RS5_PDiS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb1EE6do_outER11__mbstate_tPKDiS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDiLb1EE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb0EE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb0EE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb0EE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb0EE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb0EE5do_inER11__mbstate_tPKcS5_RS5_PDsS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb0EE6do_outER11__mbstate_tPKDsS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb0EE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb1EE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb1EE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb1EE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb1EE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb1EE5do_inER11__mbstate_tPKcS5_RS5_PDsS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb1EE6do_outER11__mbstate_tPKDsS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IDsLb1EE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb0EE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb0EE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb0EE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb0EE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb0EE5do_inER11__mbstate_tPKcS5_RS5_PwS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb0EE6do_outER11__mbstate_tPKwS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb0EE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb1EE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb1EE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb1EE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__215__codecvt_utf16IwLb1EE16do_always_noconvEv'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb0EE13do_neg_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb0EE13do_pos_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb0EE14do_curr_symbolEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb0EE14do_frac_digitsEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb0EE16do_decimal_pointEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb0EE16do_negative_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb0EE16do_positive_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb0EE16do_thousands_sepEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb1EE11do_groupingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb1EE13do_neg_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb1EE13do_pos_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb1EE14do_curr_symbolEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb1EE14do_frac_digitsEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb1EE16do_decimal_pointEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb1EE16do_negative_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb1EE16do_positive_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIcLb1EE16do_thousands_sepEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb0EE11do_groupingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb0EE13do_neg_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb0EE13do_pos_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb0EE14do_curr_symbolEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb0EE14do_frac_digitsEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb0EE16do_decimal_pointEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb0EE16do_negative_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb0EE16do_positive_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb0EE16do_thousands_sepEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb1EE11do_groupingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb1EE13do_neg_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb1EE13do_pos_formatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb1EE14do_curr_symbolEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb1EE14do_frac_digitsEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb1EE16do_decimal_pointEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb1EE16do_negative_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb1EE16do_positive_signEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__217moneypunct_bynameIwLb1EE16do_thousands_sepEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__218__time_get_storageIcE15__do_date_orderEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__218__time_get_storageIwE15__do_date_orderEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__219__shared_weak_count13__get_deleterERKSt9type_info'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDiE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDiE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDiE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDiE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDiE5do_inER11__mbstate_tPKcS5_RS5_PDiS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDiE6do_outER11__mbstate_tPKDiS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDiE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDsE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDsE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDsE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDsE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDsE5do_inER11__mbstate_tPKcS5_RS5_PDsS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDsE6do_outER11__mbstate_tPKDsS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IDsE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IwE10do_unshiftER11__mbstate_tPcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IwE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IwE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IwE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IwE5do_inER11__mbstate_tPKcS5_RS5_PwS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IwE6do_outER11__mbstate_tPKwS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__codecvt_utf8_utf16IwE9do_lengthER11__mbstate_tPKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIcE3__XEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIcE3__cEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIcE3__rEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIcE3__xEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIcE7__am_pmEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIcE7__weeksEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIcE8__monthsEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIwE3__XEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIwE3__cEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIwE3__rEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIwE3__xEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIwE7__am_pmEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIwE7__weeksEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__time_get_c_storageIwE8__monthsEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__vector_base_commonILb1EE20__throw_length_errorEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__220__vector_base_commonILb1EE20__throw_out_of_rangeEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__221__basic_string_commonILb1EE20__throw_length_errorEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__221__basic_string_commonILb1EE20__throw_out_of_rangeEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__223__match_any_but_newlineIcE6__execERNS_7__stateIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__223__match_any_but_newlineIwE6__execERNS_7__stateIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__224__libcpp_debug_exception4whatEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE10do_tolowerEPcPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE10do_tolowerEc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE10do_toupperEPcPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE10do_toupperEc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE8do_widenEPKcS3_Pc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE8do_widenEc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE9do_narrowEPKcS3_cPc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIcE9do_narrowEcc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE10do_scan_isEjPKwS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE10do_tolowerEPwPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE10do_tolowerEw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE10do_toupperEPwPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE10do_toupperEw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE11do_scan_notEjPKwS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE5do_isEPKwS3_Pj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE5do_isEjw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE8do_widenEPKcS3_Pw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE8do_widenEc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE9do_narrowEPKwS3_cPc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__25ctypeIwE9do_narrowEwc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__26locale4nameEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__26locale9has_facetERNS0_2idE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__26locale9use_facetERNS0_2idE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__26localeeqERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDic11__mbstate_tE10do_unshiftERS1_PcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDic11__mbstate_tE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDic11__mbstate_tE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDic11__mbstate_tE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDic11__mbstate_tE5do_inERS1_PKcS5_RS5_PDiS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDic11__mbstate_tE6do_outERS1_PKDiS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDic11__mbstate_tE9do_lengthERS1_PKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDsc11__mbstate_tE10do_unshiftERS1_PcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDsc11__mbstate_tE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDsc11__mbstate_tE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDsc11__mbstate_tE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDsc11__mbstate_tE5do_inERS1_PKcS5_RS5_PDsS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDsc11__mbstate_tE6do_outERS1_PKDsS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIDsc11__mbstate_tE9do_lengthERS1_PKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIcc11__mbstate_tE10do_unshiftERS1_PcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIcc11__mbstate_tE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIcc11__mbstate_tE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIcc11__mbstate_tE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIcc11__mbstate_tE5do_inERS1_PKcS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIcc11__mbstate_tE6do_outERS1_PKcS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIcc11__mbstate_tE9do_lengthERS1_PKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIwc11__mbstate_tE10do_unshiftERS1_PcS4_RS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIwc11__mbstate_tE11do_encodingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIwc11__mbstate_tE13do_max_lengthEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIwc11__mbstate_tE16do_always_noconvEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIwc11__mbstate_tE5do_inERS1_PKcS5_RS5_PwS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIwc11__mbstate_tE6do_outERS1_PKwS5_RS5_PcS7_RS7_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27codecvtIwc11__mbstate_tE9do_lengthERS1_PKcS5_m'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27collateIcE10do_compareEPKcS3_S3_S3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27collateIcE12do_transformEPKcS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27collateIcE7do_hashEPKcS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27collateIwE10do_compareEPKwS3_S3_S3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27collateIwE12do_transformEPKwS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27collateIwE7do_hashEPKwS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRb'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRd'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRf'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRt'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRx'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjRy'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjS8_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRb'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRd'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRf'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRt'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRx'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjRy'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjS8_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcPKv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcb'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcd'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEce'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcx'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcy'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwPKv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwb'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwd'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwx'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwy'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28ios_base6getlocEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28messagesIcE6do_getEliiRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28messagesIcE7do_openERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_6localeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28messagesIcE8do_closeEl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28messagesIwE6do_getEliiRKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28messagesIwE7do_openERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_6localeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28messagesIwE8do_closeEl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28numpunctIcE11do_groupingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28numpunctIcE11do_truenameEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28numpunctIcE12do_falsenameEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28numpunctIcE16do_decimal_pointEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28numpunctIcE16do_thousands_sepEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28numpunctIwE11do_groupingEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28numpunctIwE11do_truenameEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28numpunctIwE12do_falsenameEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28numpunctIwE16do_decimal_pointEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28numpunctIwE16do_thousands_sepEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE10__get_hourERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE10__get_yearERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11__get_am_pmERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11__get_monthERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11__get_year4ERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11do_get_dateES4_S4_RNS_8ios_baseERjP2tm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11do_get_timeES4_S4_RNS_8ios_baseERjP2tm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE11do_get_yearES4_S4_RNS_8ios_baseERjP2tm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE12__get_minuteERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE12__get_secondERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE13__get_12_hourERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE13__get_percentERS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE13__get_weekdayERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE13do_date_orderEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE14do_get_weekdayES4_S4_RNS_8ios_baseERjP2tm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE15__get_monthnameERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE16do_get_monthnameES4_S4_RNS_8ios_baseERjP2tm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE17__get_weekdaynameERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE17__get_white_spaceERS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE18__get_day_year_numERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE3getES4_S4_RNS_8ios_baseERjP2tmPKcSC_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_RNS_8ios_baseERjP2tmcc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE9__get_dayERiRS4_S4_RjRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE10__get_hourERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE10__get_yearERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11__get_am_pmERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11__get_monthERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11__get_year4ERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11do_get_dateES4_S4_RNS_8ios_baseERjP2tm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11do_get_timeES4_S4_RNS_8ios_baseERjP2tm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE11do_get_yearES4_S4_RNS_8ios_baseERjP2tm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE12__get_minuteERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE12__get_secondERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE13__get_12_hourERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE13__get_percentERS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE13__get_weekdayERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE13do_date_orderEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE14do_get_weekdayES4_S4_RNS_8ios_baseERjP2tm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE15__get_monthnameERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE16do_get_monthnameES4_S4_RNS_8ios_baseERjP2tm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE17__get_weekdaynameERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE17__get_white_spaceERS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE18__get_day_year_numERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE3getES4_S4_RNS_8ios_baseERjP2tmPKwSC_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_RNS_8ios_baseERjP2tmcc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE9__get_dayERiRS4_S4_RjRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE3putES4_RNS_8ios_baseEcPK2tmPKcSC_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_RNS_8ios_baseEcPK2tmcc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE3putES4_RNS_8ios_baseEwPK2tmPKwSC_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__28time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_RNS_8ios_baseEwPK2tmcc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29__num_getIcE10__do_widenERNS_8ios_baseEPc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29__num_getIcE12__do_widen_pERNS_8ios_baseEPc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29__num_getIwE10__do_widenERNS_8ios_baseEPw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29__num_getIwE12__do_widen_pERNS_8ios_baseEPc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_bRNS_8ios_baseERjRNS_12basic_stringIcS3_NS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_getES4_S4_bRNS_8ios_baseERjRe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_bRNS_8ios_baseERjRNS_12basic_stringIwS3_NS_9allocatorIwEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_getES4_S4_bRNS_8ios_baseERjRe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_bRNS_8ios_baseEcRKNS_12basic_stringIcS3_NS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE6do_putES4_bRNS_8ios_baseEce'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_bRNS_8ios_baseEwRKNS_12basic_stringIwS3_NS_9allocatorIwEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNKSt3__29money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE6do_putES4_bRNS_8ios_baseEwe'} +{'type': 'U', 'is_defined': False, 'name': '__ZNKSt8bad_cast4whatEv'} +{'type': 'I', 'is_defined': True, 'name': '__ZNKSt8bad_cast4whatEv'} +{'type': 'U', 'is_defined': False, 'name': '__ZNKSt9bad_alloc4whatEv'} +{'type': 'I', 'is_defined': True, 'name': '__ZNKSt9bad_alloc4whatEv'} +{'type': 'U', 'is_defined': False, 'name': '__ZNKSt9exception4whatEv'} +{'type': 'I', 'is_defined': True, 'name': '__ZNKSt9exception4whatEv'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt10bad_typeidC1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt10bad_typeidC1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt10bad_typeidC2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt10bad_typeidC2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt10bad_typeidD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt10bad_typeidD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt10bad_typeidD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt10bad_typeidD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt10bad_typeidD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt10bad_typeidD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt11logic_errorC1EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt11logic_errorC1ERKNSt3__212basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt11logic_errorC1ERKS_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt11logic_errorC2EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt11logic_errorC2ERKNSt3__212basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt11logic_errorC2ERKS_'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt11logic_errorD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt11logic_errorD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt11logic_errorD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt11logic_errorD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt11logic_errorD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt11logic_errorD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt11logic_erroraSERKS_'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt11range_errorD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt11range_errorD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt11range_errorD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt11range_errorD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt11range_errorD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt11range_errorD2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt12domain_errorD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt12domain_errorD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt12domain_errorD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt12domain_errorD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt12domain_errorD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt12domain_errorD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt12experimental19bad_optional_accessD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt12experimental19bad_optional_accessD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt12experimental19bad_optional_accessD2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt12length_errorD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt12length_errorD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt12length_errorD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt12length_errorD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt12length_errorD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt12length_errorD2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt12out_of_rangeD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt12out_of_rangeD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt12out_of_rangeD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt12out_of_rangeD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt12out_of_rangeD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt12out_of_rangeD2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt13bad_exceptionD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt13bad_exceptionD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt13bad_exceptionD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt13bad_exceptionD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt13bad_exceptionD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt13bad_exceptionD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13exception_ptrC1ERKS_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13exception_ptrC2ERKS_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13exception_ptrD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13exception_ptrD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13exception_ptraSERKS_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13runtime_errorC1EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13runtime_errorC1ERKNSt3__212basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13runtime_errorC1ERKS_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13runtime_errorC2EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13runtime_errorC2ERKNSt3__212basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13runtime_errorC2ERKS_'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt13runtime_errorD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt13runtime_errorD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt13runtime_errorD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt13runtime_errorD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt13runtime_errorD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt13runtime_errorD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt13runtime_erroraSERKS_'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt14overflow_errorD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt14overflow_errorD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt14overflow_errorD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt14overflow_errorD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt14overflow_errorD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt14overflow_errorD2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt15underflow_errorD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt15underflow_errorD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt15underflow_errorD1Ev'} +{'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'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt16invalid_argumentD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt16invalid_argumentD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt16invalid_argumentD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt16nested_exceptionC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt16nested_exceptionC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt16nested_exceptionD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt16nested_exceptionD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt16nested_exceptionD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt19bad_optional_accessD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt19bad_optional_accessD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt19bad_optional_accessD2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt20bad_array_new_lengthC1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt20bad_array_new_lengthC1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt20bad_array_new_lengthC2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt20bad_array_new_lengthC2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt20bad_array_new_lengthD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt20bad_array_new_lengthD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt20bad_array_new_lengthD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt20bad_array_new_lengthD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt20bad_array_new_lengthD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt20bad_array_new_lengthD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_getC1EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_getC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_getC2EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_getC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_getD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_getD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_putC1EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_putC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_putC2EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_putC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_putD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210__time_putD2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210adopt_lockE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5alnumE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5alphaE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5blankE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5cntrlE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5digitE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5graphE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5lowerE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5printE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5punctE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5spaceE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base5upperE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210ctype_base6xdigitE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210defer_lockE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210istrstreamD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210istrstreamD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210istrstreamD2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210moneypunctIcLb0EE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210moneypunctIcLb0EE4intlE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210moneypunctIcLb1EE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210moneypunctIcLb1EE4intlE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210moneypunctIwLb0EE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210moneypunctIwLb0EE4intlE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210moneypunctIwLb1EE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__210moneypunctIwLb1EE4intlE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210ostrstreamD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210ostrstreamD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210ostrstreamD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210to_wstringEd'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210to_wstringEe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210to_wstringEf'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210to_wstringEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210to_wstringEj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210to_wstringEl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210to_wstringEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210to_wstringEx'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__210to_wstringEy'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__call_onceERVmPvPFvS2_E'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_db10__insert_cEPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_db10__insert_iEPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_db11__insert_icEPvPKv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_db15__iterator_copyEPvPKv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_db16__invalidate_allEPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_db4swapEPvS1_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_db9__erase_cEPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_db9__erase_iEPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_dbC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_dbC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_dbD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__libcpp_dbD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__money_getIcE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_SF_Ri'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__money_getIwE13__gather_infoEbRKNS_6localeERNS_10money_base7patternERwS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS9_IwNSA_IwEENSC_IwEEEESJ_SJ_Ri'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__money_putIcE13__gather_infoEbbRKNS_6localeERNS_10money_base7patternERcS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESF_SF_Ri'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__money_putIcE8__formatEPcRS2_S3_jPKcS5_RKNS_5ctypeIcEEbRKNS_10money_base7patternEccRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEESL_SL_i'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__money_putIwE13__gather_infoEbbRKNS_6localeERNS_10money_base7patternERwS8_RNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERNS9_IwNSA_IwEENSC_IwEEEESJ_Ri'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211__money_putIwE8__formatEPwRS2_S3_jPKwS5_RKNS_5ctypeIwEEbRKNS_10money_base7patternEwwRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNSE_IwNSF_IwEENSH_IwEEEESQ_i'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211regex_errorC1ENS_15regex_constants10error_typeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211regex_errorC2ENS_15regex_constants10error_typeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211regex_errorD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211regex_errorD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211regex_errorD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211this_thread9sleep_forERKNS_6chrono8durationIxNS_5ratioILl1ELl1000000000EEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211timed_mutex4lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211timed_mutex6unlockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211timed_mutex8try_lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211timed_mutexC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211timed_mutexC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211timed_mutexD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__211timed_mutexD2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__211try_to_lockE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212__do_nothingEPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212__get_sp_mutEPKv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212__next_primeEm'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212__rs_default4__c_E', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212__rs_defaultC1ERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212__rs_defaultC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212__rs_defaultC2ERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212__rs_defaultC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212__rs_defaultD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212__rs_defaultD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212__rs_defaultclEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212bad_weak_ptrD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212bad_weak_ptrD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212bad_weak_ptrD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE21__grow_by_and_replaceEmmmmmmPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE2atEm'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4nposE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE5eraseEmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendERKS5_mm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6appendEmc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignEPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignERKS5_mm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6assignEmc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertENS_11__wrap_iterIPKcEEc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmRKS5_mm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6insertEmmc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6resizeEmc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmRKS5_mm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmmc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEmmmmmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9push_backEc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1ERKS5_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1ERKS5_RKS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1ERKS5_mmRKS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2ERKS5_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2ERKS5_RKS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2ERKS5_mmRKS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEaSERKS5_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEaSEc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE21__grow_by_and_replaceEmmmmmmPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE2atEm'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE4nposE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE5eraseEmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEmw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendEPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendEPKwm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendERKS5_mm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6appendEmw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignEPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignEPKwm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignERKS5_mm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6assignEmw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertENS_11__wrap_iterIPKwEEw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmPKwm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmRKS5_mm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6insertEmmw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6resizeEmw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKwm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmRKS5_mm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmmw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9__grow_byEmmmmmm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC1ERKS5_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC1ERKS5_RKS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC1ERKS5_mmRKS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC2ERKS5_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC2ERKS5_RKS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEC2ERKS5_mmRKS4_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEaSERKS5_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEaSEw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIcEC1EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIcEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIcEC2EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIcEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIcED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIcED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIcED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIwEC1EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIwEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIwEC2EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIwEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIwED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIwED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212ctype_bynameIwED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212future_errorC1ENS_10error_codeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212future_errorC2ENS_10error_codeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212future_errorD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212future_errorD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212future_errorD2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212placeholders2_1E', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212placeholders2_2E', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212placeholders2_3E', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212placeholders2_4E', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212placeholders2_5E', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212placeholders2_6E', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212placeholders2_7E', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212placeholders2_8E', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212placeholders2_9E', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__212placeholders3_10E', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambuf3strEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambuf4swapERS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambuf6__initEPclS1_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambuf6freezeEb'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambuf7seekoffExNS_8ios_base7seekdirEj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambuf7seekposENS_4fposI11__mbstate_tEEj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambuf8overflowEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambuf9pbackfailEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambuf9underflowEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC1EPFPvmEPFvS1_E'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC1EPKal'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC1EPKcl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC1EPKhl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC1EPalS1_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC1EPclS1_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC1EPhlS1_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC1El'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC2EPFPvmEPFvS1_E'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC2EPKal'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC2EPKcl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC2EPKhl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC2EPalS1_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC2EPclS1_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC2EPhlS1_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufC2El'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212strstreambufD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_error6__initERKNS_10error_codeENS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC1ENS_10error_codeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC1ENS_10error_codeEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC1ENS_10error_codeERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC1EiRKNS_14error_categoryE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC1EiRKNS_14error_categoryEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC1EiRKNS_14error_categoryERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC2ENS_10error_codeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC2ENS_10error_codeEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC2ENS_10error_codeERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC2EiRKNS_14error_categoryE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC2EiRKNS_14error_categoryEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorC2EiRKNS_14error_categoryERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__212system_errorD0Ev'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE5tellgEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEE5ungetEv'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERd'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERf'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIcNS_11char_traitsIcEEErsERs'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE5tellgEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEE5ungetEv'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERd'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERf'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERs'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_istreamIwNS_11char_traitsIwEEErsERt'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEd'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEf'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEs'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIcNS_11char_traitsIcEEElsEt'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEd'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEf'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEs'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEt'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEx'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213basic_ostreamIwNS_11char_traitsIwEEElsEy'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213random_deviceC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213random_deviceC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213random_deviceD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213random_deviceD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213random_deviceclEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213shared_futureIvED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213shared_futureIvED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__213shared_futureIvEaSERKS1_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214__get_const_dbEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214__num_get_base10__get_baseERNS_8ios_baseE'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__214__num_get_base5__srcE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214__num_put_base12__format_intEPcPKcbj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214__num_put_base14__format_floatEPcPKcj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214__num_put_base18__identify_paddingEPcS1_RKNS_8ios_baseE'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIDic11__mbstate_tED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIDic11__mbstate_tED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIDic11__mbstate_tED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIDsc11__mbstate_tED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIDsc11__mbstate_tED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIDsc11__mbstate_tED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIcc11__mbstate_tED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIcc11__mbstate_tED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIcc11__mbstate_tED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIwc11__mbstate_tED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIwc11__mbstate_tED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214codecvt_bynameIwc11__mbstate_tED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIcEC1EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIcEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIcEC2EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIcEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIcED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIcED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIcED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIwEC1EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIwEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIwEC2EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIwEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIwED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIwED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214collate_bynameIwED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214error_categoryD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214error_categoryD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__214error_categoryD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215__get_classnameEPKcb'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215__thread_struct25notify_all_at_thread_exitEPNS_18condition_variableEPNS_5mutexE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215__thread_struct27__make_ready_at_thread_exitEPNS_17__assoc_sub_stateE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215__thread_structC1Ev'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEEC2ERKS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEEC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIcNS_11char_traitsIcEEED0Ev'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEEC2ERKS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEEC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215basic_streambufIwNS_11char_traitsIwEEEaSERKS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215future_categoryEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIcE6__initEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIcEC1EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIcEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIcEC2EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIcEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIcED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIcED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIcED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIwE6__initEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIwEC1EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIwEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIwEC2EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIwEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIwED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIwED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215numpunct_bynameIwED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215recursive_mutex4lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215recursive_mutex6unlockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215recursive_mutex8try_lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215recursive_mutexC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215recursive_mutexC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215recursive_mutexD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215recursive_mutexD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__215system_categoryEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__216__check_groupingERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPjS8_Rj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__216__narrow_to_utf8ILm16EED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__216__narrow_to_utf8ILm16EED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__216__narrow_to_utf8ILm16EED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__216__narrow_to_utf8ILm32EED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__216__narrow_to_utf8ILm32EED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__216__narrow_to_utf8ILm32EED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__216generic_categoryEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__assoc_sub_state10__sub_waitERNS_11unique_lockINS_5mutexEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__assoc_sub_state12__make_readyEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__assoc_sub_state13set_exceptionESt13exception_ptr'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__assoc_sub_state16__on_zero_sharedEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__assoc_sub_state24set_value_at_thread_exitEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__assoc_sub_state28set_exception_at_thread_exitESt13exception_ptr'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__assoc_sub_state4copyEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__assoc_sub_state4waitEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__assoc_sub_state9__executeEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__assoc_sub_state9set_valueEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__widen_from_utf8ILm16EED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__widen_from_utf8ILm16EED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__widen_from_utf8ILm16EED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__widen_from_utf8ILm32EED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__widen_from_utf8ILm32EED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217__widen_from_utf8ILm32EED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217bad_function_callD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217bad_function_callD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217bad_function_callD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217declare_reachableEPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217iostream_categoryEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217moneypunct_bynameIcLb0EE4initEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217moneypunct_bynameIcLb1EE4initEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217moneypunct_bynameIwLb0EE4initEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__217moneypunct_bynameIwLb1EE4initEPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIcE4initERKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIcE9__analyzeEcRKNS_5ctypeIcEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIcEC1EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIcEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIcEC2EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIcEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIwE4initERKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIwE9__analyzeEcRKNS_5ctypeIwEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIwEC1EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIwEC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIwEC2EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218__time_get_storageIwEC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218condition_variable10notify_allEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218condition_variable10notify_oneEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218condition_variable15__do_timed_waitERNS_11unique_lockINS_5mutexEEENS_6chrono10time_pointINS5_12system_clockENS5_8durationIxNS_5ratioILl1ELl1000000000EEEEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218condition_variable4waitERNS_11unique_lockINS_5mutexEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218condition_variableD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218condition_variableD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218shared_timed_mutex11lock_sharedEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218shared_timed_mutex13unlock_sharedEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218shared_timed_mutex15try_lock_sharedEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218shared_timed_mutex4lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218shared_timed_mutex6unlockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218shared_timed_mutex8try_lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218shared_timed_mutexC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__218shared_timed_mutexC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_mutex_base11lock_sharedEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_mutex_base13unlock_sharedEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_mutex_base15try_lock_sharedEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_mutex_base4lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_mutex_base6unlockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_mutex_base8try_lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_mutex_baseC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_mutex_baseC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_weak_count14__release_weakEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_weak_count4lockEv'} +{'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'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221recursive_timed_mutex6unlockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221recursive_timed_mutex8try_lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221recursive_timed_mutexC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221recursive_timed_mutexC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221recursive_timed_mutexD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221recursive_timed_mutexD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221undeclare_no_pointersEPcm'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__223__libcpp_debug_functionE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC1ERKNS_19__libcpp_debug_infoE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC1ERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC2ERKNS_19__libcpp_debug_infoE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC2ERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__224__libcpp_debug_exceptionD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__225notify_all_at_thread_exitERNS_18condition_variableENS_11unique_lockINS_5mutexEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIaaEEPaEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIccEEPcEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIddEEPdEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIeeEEPeEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIffEEPfEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIhhEEPhEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIiiEEPiEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIjjEEPjEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIllEEPlEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessImmEEPmEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIssEEPsEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIttEEPtEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIwwEEPwEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIxxEEPxEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__insertion_sort_incompleteIRNS_6__lessIyyEEPyEEbT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__227__libcpp_set_debug_functionEPFvRKNS_19__libcpp_debug_infoEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__229__libcpp_abort_debug_functionERKNS_19__libcpp_debug_infoE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__229__libcpp_throw_debug_functionERKNS_19__libcpp_debug_infoE'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__23cinE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__24cerrE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__24clogE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__24coutE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__24stodERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__24stodERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__24stofERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__24stofERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__24stoiERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__24stoiERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__24stolERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__24stolERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__24wcinE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25alignEmmRPvRm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25ctypeIcE13classic_tableEv'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__25ctypeIcE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25ctypeIcEC1EPKjbm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25ctypeIcEC2EPKjbm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25ctypeIcED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25ctypeIcED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25ctypeIcED2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__25ctypeIwE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25ctypeIwED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25ctypeIwED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25ctypeIwED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25mutex4lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25mutex6unlockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25mutex8try_lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25mutexD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25mutexD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25stoldERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25stoldERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25stollERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25stollERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25stoulERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__25stoulERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__25wcerrE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__25wclogE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__25wcoutE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIaaEEPaEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIccEEPcEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIddEEPdEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIeeEEPeEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIffEEPfEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIhhEEPhEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIiiEEPiEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIjjEEPjEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIllEEPlEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessImmEEPmEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIssEEPsEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIttEEPtEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIwwEEPwEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIxxEEPxEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26__sortIRNS_6__lessIyyEEPyEEvT0_S5_T_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26chrono12steady_clock3nowEv'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26chrono12steady_clock9is_steadyE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26chrono12system_clock11from_time_tEl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26chrono12system_clock3nowEv'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26chrono12system_clock9is_steadyE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26chrono12system_clock9to_time_tERKNS0_10time_pointIS1_NS0_8durationIxNS_5ratioILl1ELl1000000EEEEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26futureIvE3getEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26futureIvEC1EPNS_17__assoc_sub_stateE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26futureIvEC2EPNS_17__assoc_sub_stateE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26futureIvED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26futureIvED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26gslice6__initEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26locale14__install_ctorERKS0_PNS0_5facetEl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26locale2id5__getEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26locale2id6__initEv'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26locale2id9__next_idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26locale3allE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26locale4noneE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26locale4timeE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26locale5ctypeE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26locale5facet16__on_zero_sharedEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26locale5facetD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26locale5facetD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26locale5facetD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26locale6globalERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26locale7classicEv'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26locale7collateE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26locale7numericE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26locale8__globalEv'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26locale8messagesE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__26locale8monetaryE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC1EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC1ERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC1ERKS0_PKci'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC1ERKS0_RKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC1ERKS0_S2_i'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC2EPKc'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC2ERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC2ERKS0_PKci'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC2ERKS0_RKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC2ERKS0_S2_i'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26localeaSERKS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26stoullERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPmi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26stoullERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEPmi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26thread20hardware_concurrencyEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26thread4joinEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26thread6detachEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26threadD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__26threadD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27__sort5IRNS_6__lessIeeEEPeEEjT0_S5_S5_S5_S5_T_'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__27codecvtIDic11__mbstate_tE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIDic11__mbstate_tED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIDic11__mbstate_tED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIDic11__mbstate_tED2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__27codecvtIDsc11__mbstate_tE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIDsc11__mbstate_tED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIDsc11__mbstate_tED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIDsc11__mbstate_tED2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__27codecvtIcc11__mbstate_tE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIcc11__mbstate_tED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIcc11__mbstate_tED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIcc11__mbstate_tED2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__27codecvtIwc11__mbstate_tE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIwc11__mbstate_tEC1EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIwc11__mbstate_tEC1Em'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIwc11__mbstate_tEC2EPKcm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIwc11__mbstate_tEC2Em'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIwc11__mbstate_tED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIwc11__mbstate_tED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27codecvtIwc11__mbstate_tED2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__27collateIcE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27collateIcED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27collateIcED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27collateIcED2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__27collateIwE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27collateIwED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27collateIwED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27collateIwED2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27promiseIvE10get_futureEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27promiseIvE13set_exceptionESt13exception_ptr'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27promiseIvE24set_value_at_thread_exitEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27promiseIvE28set_exception_at_thread_exitESt13exception_ptr'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27promiseIvE9set_valueEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27promiseIvEC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27promiseIvEC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27promiseIvED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__27promiseIvED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28__c_node5__addEPNS_8__i_nodeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28__c_nodeD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28__c_nodeD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28__c_nodeD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28__get_dbEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28__i_nodeD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28__i_nodeD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28__rs_getEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28__sp_mut4lockEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28__sp_mut6unlockEv'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base10floatfieldE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base10scientificE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base11adjustfieldE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base15sync_with_stdioEb'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base16__call_callbacksENS0_5eventE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base17register_callbackEPFvNS0_5eventERS0_iEi'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base2inE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base33__set_badbit_and_consider_rethrowEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base34__set_failbit_and_consider_rethrowEv'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base3appE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base3ateE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base3decE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base3hexE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base3octE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base3outE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base4InitC1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base4InitC2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base4InitD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base4InitD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base4initEPv'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base4leftE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base4moveERS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base4swapERS0_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base5clearEj'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base5fixedE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base5imbueERKNS_6localeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base5iwordEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base5pwordEi'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base5rightE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base5truncE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base6badbitE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base6binaryE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base6eofbitE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base6skipwsE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base6xallocEv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base7copyfmtERKS0_'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base7failbitE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base7failureC1EPKcRKNS_10error_codeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base7failureC1ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_10error_codeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base7failureC2EPKcRKNS_10error_codeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base7failureC2ERKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKNS_10error_codeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base7failureD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base7failureD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_base7failureD2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base7goodbitE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base7showposE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base7unitbufE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base8internalE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base8showbaseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base9__xindex_E', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base9basefieldE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base9boolalphaE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base9showpointE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28ios_base9uppercaseE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_baseD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_baseD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28ios_baseD2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28messagesIcE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28messagesIwE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28numpunctIcE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28numpunctIcEC1Em'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28numpunctIcEC2Em'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28numpunctIcED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28numpunctIcED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28numpunctIcED2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28numpunctIwE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28numpunctIwEC1Em'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28numpunctIwEC2Em'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28numpunctIwED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28numpunctIwED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__28numpunctIwED2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0} +{'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_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_getIcE19__stage2_float_prepERNS_8ios_baseEPcRcS5_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_getIwE17__stage2_int_loopEwiPcRS2_RjwRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPjRSD_PKw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_getIwE17__stage2_int_prepERNS_8ios_baseERw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_getIwE19__stage2_float_loopEwRbRcPcRS4_wwRKNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPjRSE_RjPw'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_getIwE19__stage2_float_prepERNS_8ios_baseEPwRwS5_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_putIcE21__widen_and_group_intEPcS2_S2_S2_RS2_S3_RKNS_6localeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_putIcE23__widen_and_group_floatEPcS2_S2_S2_RS2_S3_RKNS_6localeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_putIwE21__widen_and_group_intEPcS2_S2_PwRS3_S4_RKNS_6localeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29__num_putIwE23__widen_and_group_floatEPcS2_S2_PwRS3_S4_RKNS_6localeE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29basic_iosIcNS_11char_traitsIcEEE7copyfmtERKS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29basic_iosIcNS_11char_traitsIcEEED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29basic_iosIcNS_11char_traitsIcEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29basic_iosIcNS_11char_traitsIcEEED2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29basic_iosIwNS_11char_traitsIwEEE7copyfmtERKS3_'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29basic_iosIwNS_11char_traitsIwEEED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29basic_iosIwNS_11char_traitsIwEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29basic_iosIwNS_11char_traitsIwEEED2Ev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__29money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEE8__do_getERS4_S4_bRKNS_6localeEjRjRbRKNS_5ctypeIcEERNS_10unique_ptrIcPFvPvEEERPcSM_'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__29money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEE8__do_getERS4_S4_bRKNS_6localeEjRjRbRKNS_5ctypeIwEERNS_10unique_ptrIwPFvPvEEERPwSM_'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__29money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEE2idE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__29money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEE2idE', 'size': 0} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29strstreamD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29strstreamD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29strstreamD2Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29to_stringEd'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29to_stringEe'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29to_stringEf'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29to_stringEi'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29to_stringEj'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29to_stringEl'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29to_stringEm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29to_stringEx'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__29to_stringEy'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__2plIcNS_11char_traitsIcEENS_9allocatorIcEEEENS_12basic_stringIT_T0_T1_EEPKS6_RKS9_'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt8bad_castC1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt8bad_castC1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt8bad_castC2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt8bad_castC2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt8bad_castD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt8bad_castD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt8bad_castD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt8bad_castD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt8bad_castD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt8bad_castD2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9bad_allocC1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9bad_allocC1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9bad_allocC2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9bad_allocC2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9bad_allocD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9bad_allocD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9bad_allocD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9bad_allocD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9bad_allocD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9bad_allocD2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9exceptionD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9exceptionD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9exceptionD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9exceptionD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9exceptionD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9exceptionD2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9type_infoD0Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9type_infoD0Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9type_infoD1Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9type_infoD1Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZNSt9type_infoD2Ev'} +{'type': 'I', 'is_defined': True, 'name': '__ZNSt9type_infoD2Ev'} +{'type': 'U', 'is_defined': False, 'name': '__ZSt10unexpectedv'} +{'type': 'I', 'is_defined': True, 'name': '__ZSt10unexpectedv'} +{'type': 'U', 'is_defined': False, 'name': '__ZSt13get_terminatev'} +{'type': 'I', 'is_defined': True, 'name': '__ZSt13get_terminatev'} +{'type': 'U', 'is_defined': False, 'name': '__ZSt13set_terminatePFvvE'} +{'type': 'I', 'is_defined': True, 'name': '__ZSt13set_terminatePFvvE'} +{'type': 'U', 'is_defined': False, 'name': '__ZSt14get_unexpectedv'} +{'type': 'I', 'is_defined': True, 'name': '__ZSt14get_unexpectedv'} +{'type': 'U', 'is_defined': False, 'name': '__ZSt14set_unexpectedPFvvE'} +{'type': 'I', 'is_defined': True, 'name': '__ZSt14set_unexpectedPFvvE'} +{'type': 'U', 'is_defined': False, 'name': '__ZSt15get_new_handlerv'} +{'type': 'I', 'is_defined': True, 'name': '__ZSt15get_new_handlerv'} +{'type': 'U', 'is_defined': False, 'name': '__ZSt15set_new_handlerPFvvE'} +{'type': 'I', 'is_defined': True, 'name': '__ZSt15set_new_handlerPFvvE'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZSt17__throw_bad_allocv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZSt17current_exceptionv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZSt17rethrow_exceptionSt13exception_ptr'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZSt18uncaught_exceptionv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZSt19uncaught_exceptionsv'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZSt7nothrow', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZSt9terminatev'} +{'type': 'I', 'is_defined': True, 'name': '__ZSt9terminatev'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTCNSt3__210istrstreamE0_NS_13basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTCNSt3__210ostrstreamE0_NS_13basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTCNSt3__214basic_iostreamIcNS_11char_traitsIcEEEE0_NS_13basic_istreamIcS2_EE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTCNSt3__214basic_iostreamIcNS_11char_traitsIcEEEE16_NS_13basic_ostreamIcS2_EE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTCNSt3__29strstreamE0_NS_13basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTCNSt3__29strstreamE0_NS_14basic_iostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTCNSt3__29strstreamE16_NS_13basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTIDi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIDi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIDn'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIDn'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIDs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIDs'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt12experimental15fundamentals_v112bad_any_castE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt12experimental19bad_optional_accessE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__210__time_getE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__210__time_putE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__210ctype_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__210istrstreamE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__210money_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__210moneypunctIcLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__210moneypunctIcLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__210moneypunctIwLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__210moneypunctIwLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__210ostrstreamE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__211__money_getIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__211__money_getIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__211__money_putIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__211__money_putIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__211regex_errorE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__212bad_weak_ptrE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__212codecvt_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__212ctype_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__212ctype_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__212future_errorE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__212strstreambufE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__212system_errorE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__213basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__213basic_istreamIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__213basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__213basic_ostreamIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__213messages_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214__codecvt_utf8IDiEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214__codecvt_utf8IDsEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214__codecvt_utf8IwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214__num_get_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214__num_put_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214__shared_countE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214basic_iostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214codecvt_bynameIDic11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214codecvt_bynameIDsc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214codecvt_bynameIcc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214codecvt_bynameIwc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214collate_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214collate_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__214error_categoryE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215__codecvt_utf16IDiLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215__codecvt_utf16IDiLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215__codecvt_utf16IDsLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215__codecvt_utf16IDsLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215__codecvt_utf16IwLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215__codecvt_utf16IwLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215basic_streambufIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215basic_streambufIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215messages_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215messages_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215numpunct_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215numpunct_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215time_get_bynameIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215time_get_bynameIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215time_put_bynameIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__215time_put_bynameIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__216__narrow_to_utf8ILm16EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__216__narrow_to_utf8ILm32EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__217__assoc_sub_stateE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__217__widen_from_utf8ILm16EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__217__widen_from_utf8ILm32EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__217bad_function_callE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__217moneypunct_bynameIcLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__217moneypunct_bynameIcLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__217moneypunct_bynameIwLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__217moneypunct_bynameIwLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__218__time_get_storageIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__218__time_get_storageIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__219__shared_weak_countE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__220__codecvt_utf8_utf16IDiEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__220__codecvt_utf8_utf16IDsEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__220__codecvt_utf8_utf16IwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__220__time_get_c_storageIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__220__time_get_c_storageIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__224__libcpp_debug_exceptionE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__25ctypeIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__25ctypeIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__26locale5facetE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__27codecvtIDic11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__27codecvtIDsc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__27codecvtIcc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__27codecvtIwc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__27collateIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__27collateIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28__c_nodeE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28ios_base7failureE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28ios_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28messagesIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28messagesIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28numpunctIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28numpunctIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__28time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29__num_getIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29__num_getIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29__num_putIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29__num_putIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29basic_iosIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29basic_iosIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29strstreamE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTINSt3__29time_baseE', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPDi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPDi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPDn'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPDn'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPDs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPDs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKDi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKDi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKDn'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKDn'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKDs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKDs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKa'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKa'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKb'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKb'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKc'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKc'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKd'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKd'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKe'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKe'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKf'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKf'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKh'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKh'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKj'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKj'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKl'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKl'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKm'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKm'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKt'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKt'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKv'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKv'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKw'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKw'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKx'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKx'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPKy'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPKy'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPa'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPa'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPb'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPb'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPc'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPc'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPd'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPd'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPe'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPe'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPf'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPf'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPh'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPh'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPj'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPj'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPl'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPl'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPm'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPm'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPt'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPt'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPv'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPv'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPw'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPw'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPx'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPx'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIPy'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIPy'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt10bad_typeid'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt10bad_typeid'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt11logic_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt11logic_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt11range_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt11range_error'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTISt12bad_any_cast', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt12domain_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt12domain_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt12length_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt12length_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt12out_of_range'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt12out_of_range'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt13bad_exception'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt13bad_exception'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt13runtime_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt13runtime_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt14overflow_error'} +{'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} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTISt18bad_variant_access', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTISt19bad_optional_access', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt20bad_array_new_length'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt20bad_array_new_length'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt8bad_cast'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt8bad_cast'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt9bad_alloc'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt9bad_alloc'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt9exception'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt9exception'} +{'type': 'U', 'is_defined': False, 'name': '__ZTISt9type_info'} +{'type': 'I', 'is_defined': True, 'name': '__ZTISt9type_info'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIa'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIa'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIb'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIb'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIc'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIc'} +{'type': 'U', 'is_defined': False, 'name': '__ZTId'} +{'type': 'I', 'is_defined': True, 'name': '__ZTId'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIe'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIe'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIf'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIf'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIh'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIh'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIj'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIj'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIl'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIl'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIm'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIm'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIt'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIt'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIv'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIv'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIw'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIw'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIx'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIx'} +{'type': 'U', 'is_defined': False, 'name': '__ZTIy'} +{'type': 'I', 'is_defined': True, 'name': '__ZTIy'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSDi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSDi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSDn'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSDn'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSDs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSDs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSN10__cxxabiv116__enum_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSN10__cxxabiv116__enum_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSN10__cxxabiv117__array_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSN10__cxxabiv117__array_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSN10__cxxabiv117__class_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSN10__cxxabiv117__class_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSN10__cxxabiv117__pbase_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSN10__cxxabiv117__pbase_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSN10__cxxabiv119__pointer_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSN10__cxxabiv119__pointer_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSN10__cxxabiv120__function_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSN10__cxxabiv120__function_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSN10__cxxabiv120__si_class_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSN10__cxxabiv120__si_class_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSN10__cxxabiv121__vmi_class_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSN10__cxxabiv121__vmi_class_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSN10__cxxabiv123__fundamental_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSN10__cxxabiv123__fundamental_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSN10__cxxabiv129__pointer_to_member_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSN10__cxxabiv129__pointer_to_member_type_infoE'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt12experimental15fundamentals_v112bad_any_castE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt12experimental19bad_optional_accessE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__210__time_getE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__210__time_putE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__210ctype_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__210istrstreamE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__210money_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__210moneypunctIcLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__210moneypunctIcLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__210moneypunctIwLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__210moneypunctIwLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__210ostrstreamE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__211__money_getIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__211__money_getIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__211__money_putIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__211__money_putIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__211regex_errorE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__212bad_weak_ptrE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__212codecvt_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__212ctype_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__212ctype_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__212future_errorE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__212strstreambufE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__212system_errorE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__213basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__213basic_istreamIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__213basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__213basic_ostreamIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__213messages_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214__codecvt_utf8IDiEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214__codecvt_utf8IDsEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214__codecvt_utf8IwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214__num_get_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214__num_put_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214__shared_countE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214basic_iostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214codecvt_bynameIDic11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214codecvt_bynameIDsc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214codecvt_bynameIcc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214codecvt_bynameIwc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214collate_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214collate_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__214error_categoryE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215__codecvt_utf16IDiLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215__codecvt_utf16IDiLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215__codecvt_utf16IDsLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215__codecvt_utf16IDsLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215__codecvt_utf16IwLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215__codecvt_utf16IwLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215basic_streambufIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215basic_streambufIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215messages_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215messages_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215numpunct_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215numpunct_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215time_get_bynameIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215time_get_bynameIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215time_put_bynameIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__215time_put_bynameIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__216__narrow_to_utf8ILm16EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__216__narrow_to_utf8ILm32EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__217__assoc_sub_stateE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__217__widen_from_utf8ILm16EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__217__widen_from_utf8ILm32EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__217bad_function_callE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__217moneypunct_bynameIcLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__217moneypunct_bynameIcLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__217moneypunct_bynameIwLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__217moneypunct_bynameIwLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__218__time_get_storageIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__218__time_get_storageIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__219__shared_weak_countE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__220__codecvt_utf8_utf16IDiEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__220__codecvt_utf8_utf16IDsEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__220__codecvt_utf8_utf16IwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__220__time_get_c_storageIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__220__time_get_c_storageIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__224__libcpp_debug_exceptionE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__25ctypeIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__25ctypeIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__26locale5facetE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__27codecvtIDic11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__27codecvtIDsc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__27codecvtIcc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__27codecvtIwc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__27collateIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__27collateIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28__c_nodeE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28ios_base7failureE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28ios_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28messagesIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28messagesIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28numpunctIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28numpunctIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__28time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29__num_getIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29__num_getIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29__num_putIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29__num_putIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29basic_iosIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29basic_iosIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29strstreamE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSNSt3__29time_baseE', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPDi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPDi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPDn'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPDn'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPDs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPDs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKDi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKDi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKDn'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKDn'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKDs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKDs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKa'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKa'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKb'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKb'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKc'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKc'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKd'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKd'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKe'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKe'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKf'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKf'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKh'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKh'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKj'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKj'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKl'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKl'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKm'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKm'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKt'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKt'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKv'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKv'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKw'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKw'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKx'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKx'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPKy'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPKy'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPa'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPa'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPb'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPb'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPc'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPc'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPd'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPd'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPe'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPe'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPf'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPf'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPh'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPh'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPj'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPj'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPl'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPl'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPm'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPm'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPt'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPt'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPv'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPv'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPw'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPw'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPx'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPx'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSPy'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSPy'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt10bad_typeid'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt10bad_typeid'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt11logic_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt11logic_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt11range_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt11range_error'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSSt12bad_any_cast', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt12domain_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt12domain_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt12length_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt12length_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt12out_of_range'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt12out_of_range'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt13bad_exception'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt13bad_exception'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt13runtime_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt13runtime_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt14overflow_error'} +{'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} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSSt18bad_variant_access', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTSSt19bad_optional_access', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt20bad_array_new_length'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt20bad_array_new_length'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt8bad_cast'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt8bad_cast'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt9bad_alloc'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt9bad_alloc'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt9exception'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt9exception'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSSt9type_info'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSSt9type_info'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSa'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSa'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSb'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSb'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSc'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSc'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSd'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSd'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSe'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSe'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSf'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSf'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSh'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSh'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSi'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSi'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSj'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSj'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSl'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSl'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSm'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSm'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSs'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSs'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSt'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSt'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSv'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSv'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSw'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSw'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSx'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSx'} +{'type': 'U', 'is_defined': False, 'name': '__ZTSy'} +{'type': 'I', 'is_defined': True, 'name': '__ZTSy'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTTNSt3__210istrstreamE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTTNSt3__210ostrstreamE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTTNSt3__213basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTTNSt3__213basic_istreamIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTTNSt3__213basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTTNSt3__213basic_ostreamIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTTNSt3__214basic_iostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTTNSt3__29strstreamE', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTVN10__cxxabiv116__enum_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVN10__cxxabiv116__enum_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVN10__cxxabiv117__array_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVN10__cxxabiv117__array_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVN10__cxxabiv117__class_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVN10__cxxabiv117__class_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVN10__cxxabiv117__pbase_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVN10__cxxabiv117__pbase_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVN10__cxxabiv119__pointer_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVN10__cxxabiv119__pointer_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVN10__cxxabiv120__function_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVN10__cxxabiv120__function_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVN10__cxxabiv120__si_class_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVN10__cxxabiv120__si_class_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVN10__cxxabiv121__vmi_class_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVN10__cxxabiv121__vmi_class_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVN10__cxxabiv123__fundamental_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVN10__cxxabiv123__fundamental_type_infoE'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVN10__cxxabiv129__pointer_to_member_type_infoE'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVN10__cxxabiv129__pointer_to_member_type_infoE'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt12experimental15fundamentals_v112bad_any_castE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt12experimental19bad_optional_accessE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__210istrstreamE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__210moneypunctIcLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__210moneypunctIcLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__210moneypunctIwLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__210moneypunctIwLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__210ostrstreamE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__211regex_errorE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__212bad_weak_ptrE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__212ctype_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__212ctype_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__212future_errorE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__212strstreambufE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__212system_errorE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__213basic_istreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__213basic_istreamIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__213basic_ostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__213basic_ostreamIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214__codecvt_utf8IDiEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214__codecvt_utf8IDsEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214__codecvt_utf8IwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214__shared_countE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214basic_iostreamIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214codecvt_bynameIDic11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214codecvt_bynameIDsc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214codecvt_bynameIcc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214codecvt_bynameIwc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214collate_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214collate_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__214error_categoryE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215__codecvt_utf16IDiLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215__codecvt_utf16IDiLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215__codecvt_utf16IDsLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215__codecvt_utf16IDsLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215__codecvt_utf16IwLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215__codecvt_utf16IwLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215basic_streambufIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215basic_streambufIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215messages_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215messages_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215numpunct_bynameIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215numpunct_bynameIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215time_get_bynameIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215time_get_bynameIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215time_put_bynameIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__215time_put_bynameIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__216__narrow_to_utf8ILm16EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__216__narrow_to_utf8ILm32EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__217__assoc_sub_stateE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__217__widen_from_utf8ILm16EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__217__widen_from_utf8ILm32EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__217bad_function_callE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__217moneypunct_bynameIcLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__217moneypunct_bynameIcLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__217moneypunct_bynameIwLb0EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__217moneypunct_bynameIwLb1EEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__219__shared_weak_countE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__220__codecvt_utf8_utf16IDiEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__220__codecvt_utf8_utf16IDsEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__220__codecvt_utf8_utf16IwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__224__libcpp_debug_exceptionE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__25ctypeIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__25ctypeIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__26locale5facetE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__27codecvtIDic11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__27codecvtIDsc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__27codecvtIcc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__27codecvtIwc11__mbstate_tEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__27collateIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__27collateIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__27num_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__27num_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__27num_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__27num_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28__c_nodeE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28ios_base7failureE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28ios_baseE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28messagesIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28messagesIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28numpunctIcEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28numpunctIwEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28time_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28time_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28time_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__28time_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__29basic_iosIcNS_11char_traitsIcEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__29basic_iosIwNS_11char_traitsIwEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__29money_getIcNS_19istreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__29money_getIwNS_19istreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__29money_putIcNS_19ostreambuf_iteratorIcNS_11char_traitsIcEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__29money_putIwNS_19ostreambuf_iteratorIwNS_11char_traitsIwEEEEEE', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVNSt3__29strstreamE', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt10bad_typeid'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt10bad_typeid'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt11logic_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt11logic_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt11range_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt11range_error'} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVSt12bad_any_cast', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt12domain_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt12domain_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt12length_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt12length_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt12out_of_range'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt12out_of_range'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt13bad_exception'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt13bad_exception'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt13runtime_error'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt13runtime_error'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt14overflow_error'} +{'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} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVSt18bad_variant_access', 'size': 0} +{'type': 'OBJECT', 'is_defined': True, 'name': '__ZTVSt19bad_optional_access', 'size': 0} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt20bad_array_new_length'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt20bad_array_new_length'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt8bad_cast'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt8bad_cast'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt9bad_alloc'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt9bad_alloc'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt9exception'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt9exception'} +{'type': 'U', 'is_defined': False, 'name': '__ZTVSt9type_info'} +{'type': 'I', 'is_defined': True, 'name': '__ZTVSt9type_info'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZThn16_NSt3__214basic_iostreamIcNS_11char_traitsIcEEED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZThn16_NSt3__214basic_iostreamIcNS_11char_traitsIcEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZThn16_NSt3__29strstreamD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZThn16_NSt3__29strstreamD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__210istrstreamD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__210istrstreamD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__210ostrstreamD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__210ostrstreamD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__213basic_istreamIcNS_11char_traitsIcEEED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__213basic_istreamIcNS_11char_traitsIcEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__213basic_istreamIwNS_11char_traitsIwEEED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__213basic_istreamIwNS_11char_traitsIwEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__213basic_ostreamIcNS_11char_traitsIcEEED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__213basic_ostreamIcNS_11char_traitsIcEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__213basic_ostreamIwNS_11char_traitsIwEEED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__213basic_ostreamIwNS_11char_traitsIwEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__214basic_iostreamIcNS_11char_traitsIcEEED0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__214basic_iostreamIcNS_11char_traitsIcEEED1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__29strstreamD0Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZTv0_n24_NSt3__29strstreamD1Ev'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdaPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdaPvRKSt9nothrow_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdaPvSt11align_val_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdaPvSt11align_val_tRKSt9nothrow_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdaPvm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdaPvmSt11align_val_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdlPv'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdlPvRKSt9nothrow_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdlPvSt11align_val_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdlPvSt11align_val_tRKSt9nothrow_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdlPvm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZdlPvmSt11align_val_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__Znam'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZnamRKSt9nothrow_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZnamSt11align_val_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZnamSt11align_val_tRKSt9nothrow_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__Znwm'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZnwmRKSt9nothrow_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZnwmSt11align_val_t'} +{'type': 'FUNC', 'is_defined': True, 'name': '__ZnwmSt11align_val_tRKSt9nothrow_t'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_allocate_exception'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_allocate_exception'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_atexit'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_bad_cast'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_bad_cast'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_bad_typeid'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_bad_typeid'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_begin_catch'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_begin_catch'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_call_unexpected'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_call_unexpected'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_current_exception_type'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_current_exception_type'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_current_primary_exception'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_decrement_exception_refcount'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_deleted_virtual'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_deleted_virtual'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_demangle'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_demangle'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_end_catch'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_end_catch'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_free_exception'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_free_exception'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_get_exception_ptr'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_get_exception_ptr'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_get_globals'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_get_globals'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_get_globals_fast'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_get_globals_fast'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_guard_abort'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_guard_abort'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_guard_acquire'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_guard_acquire'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_guard_release'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_guard_release'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_increment_exception_refcount'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_pure_virtual'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_pure_virtual'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_rethrow'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_rethrow'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_rethrow_primary_exception'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_throw'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_throw'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_uncaught_exceptions'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_vec_cctor'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_vec_cctor'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_vec_cleanup'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_vec_cleanup'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_vec_ctor'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_vec_ctor'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_vec_delete'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_vec_delete'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_vec_delete2'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_vec_delete2'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_vec_delete3'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_vec_delete3'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_vec_dtor'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_vec_dtor'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_vec_new'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_vec_new'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_vec_new2'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_vec_new2'} +{'type': 'U', 'is_defined': False, 'name': '___cxa_vec_new3'} +{'type': 'I', 'is_defined': True, 'name': '___cxa_vec_new3'} +{'type': 'U', 'is_defined': False, 'name': '___dynamic_cast'} +{'type': 'I', 'is_defined': True, 'name': '___dynamic_cast'} +{'type': 'U', 'is_defined': False, 'name': '___gxx_personality_v0'} +{'type': 'I', 'is_defined': True, 'name': '___gxx_personality_v0'} diff --git a/lib/abi/x86_64-unknown-linux-gnu.abilist b/lib/abi/x86_64-unknown-linux-gnu.v1.abilist similarity index 100% rename from lib/abi/x86_64-unknown-linux-gnu.abilist rename to lib/abi/x86_64-unknown-linux-gnu.v1.abilist -- GitLab From e274f439c68f228846e0b78b42d10c06bc4d0142 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 20 Jul 2018 01:22:32 +0000 Subject: [PATCH 038/495] [libc++] Implement Directory Entry Caching -- Sort of. Summary: This patch implements directory_entry caching *almost* as specified in P0317r1. However, I explicitly chose to deviate from the standard as I'll explain below. The approach I decided to take is a fully caching one. When `refresh()` is called, the cache is populated by calls to `stat` and `lstat` as needed. During directory iteration the cache is only populated with the `file_type` as reported by `readdir`. The cache can be in the following states: * `_Empty`: There is nothing in the cache (likely due to an error) * `_IterSymlink`: Created by directory iteration when we walk onto a symlink only the symlink file type is known. * `_IterNonSymlink`: Created by directory iteration when we walk onto a non-symlink. Both the regular file type and symlink file type are known. * `_RefreshSymlink` and `_RefreshNonSymlink`: A full cache created by `refresh()`. This case includes dead symlinks. * `_RefreshSymlinkUnresolved`: A partial cache created by refresh when we fail to resolve the file pointed to by a symlink (likely due to permissions). Symlink attributes are cached, but attributes about the linked entity are not. As mentioned, this implementation purposefully deviates from the standard. According to some readings of the specification, and the Windows filesystem implementation, the constructors and modifiers which don't pass an `error_code` must throw when the `directory_entry` points to a entity which doesn't exist. or when attribute resolution fails for another reason. @BillyONeal has proposed a more reasonable set of requirements, where modifiers other than refresh ignore errors. This is the behavior libc++ currently implements, with the expectation some form of the new language will be accepted into the standard. Some additional semantics which differ from the Windows implementation: 1. `refresh` will not throw when the entry doesn't exist. In this case we can still meet the functions specification, so we don't treat it as an error. 2. We don't clear the path name when a constructor fails via refresh (this will hopefully be changed in the standard as well). It should be noted that libstdc++'s current implementation has the same behavior as libc++, except for point (2). If the changes to the specification don't get accepted, we'll be able to make the changes later. [1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0317r1.html Reviewers: mclow.lists, gromer, ldionne, aaron.ballman Subscribers: BillyONeal, christof, cfe-commits Differential Revision: https://reviews.llvm.org/D49530 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337516 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/experimental/filesystem | 393 +++++++++++++++++- .../filesystem/directory_iterator.cpp | 93 +++-- ...stem_time_helper.h => filesystem_common.h} | 145 ++++++- src/experimental/filesystem/operations.cpp | 357 ++++++++-------- .../last_write_time.sh.cpp | 96 +++++ .../filesystem/convert_file_time.sh.cpp | 4 +- .../directory_entry.cons.pass.cpp | 96 ----- .../directory_entry.cons/copy.pass.cpp | 74 ++++ .../directory_entry.cons/copy_assign.pass.cpp | 82 ++++ .../directory_entry.cons/default.pass.cpp | 31 ++ .../directory_entry.cons/move.pass.cpp | 72 ++++ .../directory_entry.cons/move_assign.pass.cpp | 78 ++++ .../directory_entry.cons/path.pass.cpp | 182 ++++++++ .../directory_entry.mods.pass.cpp | 112 ----- .../directory_entry.mods/assign.pass.cpp | 132 ++++++ .../directory_entry.mods/refresh.pass.cpp | 339 +++++++++++++++ .../replace_filename.pass.cpp | 169 ++++++++ .../directory_entry.obs/file_size.pass.cpp | 238 +++++++++++ .../file_type_obs.pass.cpp | 258 ++++++++++++ .../hard_link_count.pass.cpp | 237 +++++++++++ .../last_write_time.pass.cpp | 210 ++++++++++ .../directory_entry.obs/status.pass.cpp | 39 +- .../symlink_status.pass.cpp | 32 +- .../fs.op.file_size/file_size.pass.cpp | 25 +- test/support/filesystem_test_helper.hpp | 60 ++- test/support/rapid-cxx-test.hpp | 19 + www/cxx1z_status.html | 2 +- 27 files changed, 3111 insertions(+), 464 deletions(-) rename src/experimental/filesystem/{filesystem_time_helper.h => filesystem_common.h} (58%) create mode 100644 test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp delete mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.cons.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move_assign.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/path.pass.cpp delete mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.mods.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/assign.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp diff --git a/include/experimental/filesystem b/include/experimental/filesystem index 1ca179699..be73bf135 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -1903,6 +1903,10 @@ path weakly_canonical(path const& __p, error_code& __ec) { } +class directory_iterator; +class recursive_directory_iterator; +class __dir_stream; + class directory_entry { typedef _VSTD_FS::path _Path; @@ -1914,7 +1918,15 @@ public: directory_entry(directory_entry&&) _NOEXCEPT = default; _LIBCPP_INLINE_VISIBILITY - explicit directory_entry(_Path const& __p) : __p_(__p) {} + explicit directory_entry(_Path const& __p) : __p_(__p) { + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + directory_entry(_Path const& __p, error_code &__ec) : __p_(__p) { + __refresh(&__ec); + } ~directory_entry() {} @@ -1924,13 +1936,37 @@ public: _LIBCPP_INLINE_VISIBILITY void assign(_Path const& __p) { __p_ = __p; + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void assign(_Path const& __p, error_code& __ec) { + __p_ = __p; + __refresh(&__ec); } _LIBCPP_INLINE_VISIBILITY void replace_filename(_Path const& __p) { - __p_ = __p_.parent_path() / __p; + __p_.replace_filename(__p); + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void replace_filename(_Path const& __p, error_code &__ec) { + __p_ = __p_.parent_path() / __p; + __refresh(&__ec); } + _LIBCPP_INLINE_VISIBILITY + void refresh() { + __refresh(); + } + + _LIBCPP_INLINE_VISIBILITY + void refresh(error_code& __ec) _NOEXCEPT { __refresh(&__ec); } + _LIBCPP_INLINE_VISIBILITY _Path const& path() const _NOEXCEPT { return __p_; @@ -1941,24 +1977,143 @@ public: return __p_; } + _LIBCPP_INLINE_VISIBILITY + bool exists() const { + return _VSTD_FS::exists(file_status{__get_ft()}); + } + + _LIBCPP_INLINE_VISIBILITY + bool exists(error_code& __ec) const noexcept { + return _VSTD_FS::exists(file_status{__get_ft(&__ec)}); + } + + _LIBCPP_INLINE_VISIBILITY + bool is_block_file() const { + return __get_ft() == file_type::block; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_block_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::block; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_character_file() const { + return __get_ft() == file_type::character; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_character_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::character; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_directory() const { + return __get_ft() == file_type::directory; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_directory(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::directory; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_fifo() const { + return __get_ft() == file_type::fifo; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_fifo(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::fifo; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_other() const { + return _VSTD_FS::is_other(file_status{__get_ft()}); + } + + _LIBCPP_INLINE_VISIBILITY + bool is_other(error_code& __ec) const noexcept { + return _VSTD_FS::is_other(file_status{__get_ft(&__ec)}); + } + + _LIBCPP_INLINE_VISIBILITY + bool is_regular_file() const { + return __get_ft() == file_type::regular; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_regular_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::regular; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_socket() const { + return __get_ft() == file_type::socket; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_socket(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::socket; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_symlink() const { + return __get_sym_ft() == file_type::symlink; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_symlink(error_code& __ec) const noexcept { + return __get_sym_ft(&__ec) == file_type::symlink; + } + _LIBCPP_INLINE_VISIBILITY + uintmax_t file_size() const { + return __get_size(); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t file_size(error_code& __ec) const noexcept { + return __get_size(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t hard_link_count() const { + return __get_nlink(); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t hard_link_count(error_code& __ec) const noexcept { + return __get_nlink(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + file_time_type last_write_time() const { + return __get_write_time(); + } + + _LIBCPP_INLINE_VISIBILITY + file_time_type last_write_time(error_code& __ec) const noexcept { + return __get_write_time(&__ec); + } + _LIBCPP_INLINE_VISIBILITY file_status status() const { - return _VSTD_FS::status(__p_); + return __get_status(); } _LIBCPP_INLINE_VISIBILITY file_status status(error_code& __ec) const _NOEXCEPT { - return _VSTD_FS::status(__p_, __ec); + return __get_status(&__ec); } _LIBCPP_INLINE_VISIBILITY file_status symlink_status() const { - return _VSTD_FS::symlink_status(__p_); + return __get_symlink_status(); } _LIBCPP_INLINE_VISIBILITY file_status symlink_status(error_code& __ec) const _NOEXCEPT { - return _VSTD_FS::symlink_status(__p_, __ec); + return __get_symlink_status(&__ec); } _LIBCPP_INLINE_VISIBILITY @@ -1990,14 +2145,230 @@ public: bool operator>=(directory_entry const& __rhs) const _NOEXCEPT { return __p_ >= __rhs.__p_; } + private: - _Path __p_; -}; + friend class directory_iterator; + friend class recursive_directory_iterator; + friend class __dir_stream; + + enum _CacheType : unsigned char { + _Empty, + _IterSymlink, + _IterNonSymlink, + _RefreshSymlink, + _RefreshSymlinkUnresolved, + _RefreshNonSymlink + }; + struct __cached_data { + uintmax_t __size_; + uintmax_t __nlink_; + file_time_type __write_time_; + perms __sym_perms_; + perms __non_sym_perms_; + file_type __type_; + _CacheType __cache_type_; + + _LIBCPP_INLINE_VISIBILITY + __cached_data() noexcept { __reset(); } + + _LIBCPP_INLINE_VISIBILITY + void __reset() { + __cache_type_ = _Empty; + __type_ = file_type::none; + __sym_perms_ = __non_sym_perms_ = perms::unknown; + __size_ = __nlink_ = uintmax_t(-1); + __write_time_ = file_time_type::min(); + } + }; -class directory_iterator; -class recursive_directory_iterator; -class __dir_stream; + _LIBCPP_INLINE_VISIBILITY + static __cached_data __create_iter_result(file_type __ft) { + __cached_data __data; + __data.__type_ = __ft; + __data.__cache_type_ = + __ft == file_type::symlink ? _IterSymlink : _IterNonSymlink; + return __data; + } + + _LIBCPP_INLINE_VISIBILITY + void __assign_iter_entry(_Path&& __p, __cached_data __dt) { + __p_ = std::move(__p); + __data_ = __dt; + } + + _LIBCPP_FUNC_VIS + error_code __do_refresh() noexcept; + + _LIBCPP_INLINE_VISIBILITY + static bool __is_dne_error(error_code const& __ec) { + if (!__ec) + return true; + switch (static_cast(__ec.value())) { + case errc::no_such_file_or_directory: + case errc::not_a_directory: + return true; + default: + return false; + } + } + + _LIBCPP_INLINE_VISIBILITY + void __handle_error(const char* __msg, error_code* __dest_ec, + error_code const& __ec, + bool __allow_dne = false) const { + if (__dest_ec) { + *__dest_ec = __ec; + return; + } + if (__ec && (!__allow_dne || !__is_dne_error(__ec))) + __throw_filesystem_error(__msg, __p_, _Path{}, __ec); + } + + _LIBCPP_INLINE_VISIBILITY + void __refresh(error_code* __ec = nullptr) { + __handle_error("refresh", __ec, __do_refresh(), /*allow_dne*/ true); + } + + _LIBCPP_INLINE_VISIBILITY + file_type __get_sym_ft(error_code *__ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + return __symlink_status(__p_, __ec).type(); + case _IterSymlink: + case _RefreshSymlink: + case _RefreshSymlinkUnresolved: + if (__ec) + __ec->clear(); + return file_type::symlink; + case _IterNonSymlink: + case _RefreshNonSymlink: + file_status __st(__data_.__type_); + if (__ec && !_VSTD_FS::exists(__st)) + *__ec = make_error_code(errc::no_such_file_or_directory); + else if (__ec) + __ec->clear(); + return __data_.__type_; + } + } + + _LIBCPP_INLINE_VISIBILITY + file_type __get_ft(error_code *__ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return __status(__p_, __ec).type(); + case _IterNonSymlink: + case _RefreshNonSymlink: + case _RefreshSymlink: { + file_status __st(__data_.__type_); + if (__ec && !_VSTD_FS::exists(__st)) + *__ec = make_error_code(errc::no_such_file_or_directory); + else if (__ec) + __ec->clear(); + return __data_.__type_; + } + } + } + + _LIBCPP_INLINE_VISIBILITY + file_status __get_status(error_code *__ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return __status(__p_, __ec); + case _RefreshNonSymlink: + case _RefreshSymlink: + return file_status(__get_ft(__ec), __data_.__non_sym_perms_); + } + } + + _LIBCPP_INLINE_VISIBILITY + file_status __get_symlink_status(error_code *__ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + return __symlink_status(__p_, __ec); + case _RefreshNonSymlink: + return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_); + case _RefreshSymlink: + case _RefreshSymlinkUnresolved: + return file_status(__get_sym_ft(__ec), __data_.__sym_perms_); + } + } + + + _LIBCPP_INLINE_VISIBILITY + uintmax_t __get_size(error_code *__ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__file_size(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + file_status __st(__get_ft(&__m_ec)); + __handle_error("directory_entry::file_size", __ec, __m_ec); + if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) { + errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory + : errc::not_supported; + __handle_error("directory_entry::file_size", __ec, + make_error_code(__err_kind)); + } + return __data_.__size_; + } + } + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t __get_nlink(error_code *__ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__hard_link_count(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + (void)__get_ft(&__m_ec); + __handle_error("directory_entry::hard_link_count", __ec, __m_ec); + return __data_.__nlink_; + } + } + } + + _LIBCPP_INLINE_VISIBILITY + file_time_type __get_write_time(error_code *__ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__last_write_time(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + file_status __st(__get_ft(&__m_ec)); + __handle_error("directory_entry::last_write_time", __ec, __m_ec); + if (_VSTD_FS::exists(__st) && + __data_.__write_time_ == file_time_type::min()) + __handle_error("directory_entry::last_write_time", __ec, + make_error_code(errc::value_too_large)); + return __data_.__write_time_; + } + } + } +private: + _Path __p_; + __cached_data __data_; +}; class __dir_element_proxy { public: diff --git a/src/experimental/filesystem/directory_iterator.cpp b/src/experimental/filesystem/directory_iterator.cpp index a552fdc44..b0b31450e 100644 --- a/src/experimental/filesystem/directory_iterator.cpp +++ b/src/experimental/filesystem/directory_iterator.cpp @@ -17,32 +17,43 @@ #endif #include +#include "filesystem_common.h" + _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM -namespace { namespace detail { +namespace detail { +namespace { #if !defined(_LIBCPP_WIN32API) -inline error_code capture_errno() { - _LIBCPP_ASSERT(errno, "Expected errno to be non-zero"); - return error_code{errno, std::generic_category()}; +template +static file_type get_file_type(DirEntT *ent, int) { + switch (ent->d_type) { + case DT_BLK: + return file_type::block; + case DT_CHR: + return file_type::character; + case DT_DIR: + return file_type::directory; + case DT_FIFO: + return file_type::fifo; + case DT_LNK: + return file_type::symlink; + case DT_REG: + return file_type::regular; + case DT_SOCK: + return file_type::socket; + case DT_UNKNOWN: + return file_type::unknown; + } + return file_type::none; } -#endif - -template -inline bool set_or_throw(std::error_code& my_ec, - std::error_code* user_ec, - const char* msg, Args&&... args) -{ - if (user_ec) { - *user_ec = my_ec; - return true; - } - __throw_filesystem_error(msg, std::forward(args)..., my_ec); - return false; +template +static file_type get_file_type(DirEntT *ent, long) { + return file_type::unknown; } -#if !defined(_LIBCPP_WIN32API) -inline path::string_type posix_readdir(DIR *dir_stream, error_code& ec) { +static pair +posix_readdir(DIR *dir_stream, error_code& ec) { struct dirent* dir_entry_ptr = nullptr; errno = 0; // zero errno in order to detect errors ec.clear(); @@ -51,18 +62,38 @@ inline path::string_type posix_readdir(DIR *dir_stream, error_code& ec) { ec = capture_errno(); return {}; } else { - return dir_entry_ptr->d_name; + return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)}; } } +#else + +static file_type get_file_type(const WIN32_FIND_DATA& data) { + //auto attrs = data.dwFileAttributes; + // FIXME(EricWF) + return file_type::unknown; +} +static uintmax_t get_file_size(const WIN32_FIND_DATA& data) { + return (data.nFileSizeHight * (MAXDWORD+1)) + data.nFileSizeLow; +} +static file_time_type get_write_time(const WIN32_FIND_DATA& data) { + ULARGE_INTEGER tmp; + FILETIME& time = data.ftLastWriteTime; + tmp.u.LowPart = time.dwLowDateTime; + tmp.u.HighPart = time.dwHighDateTime; + return file_time_type(file_time_type::duration(time.QuadPart)); +} + #endif -}} // namespace detail +} // namespace +} // namespace detail using detail::set_or_throw; #if defined(_LIBCPP_WIN32API) class __dir_stream { public: + __dir_stream() = delete; __dir_stream& operator=(const __dir_stream&) = delete; @@ -74,7 +105,7 @@ public: __dir_stream(const path& root, directory_options opts, error_code& ec) : __stream_(INVALID_HANDLE_VALUE), __root_(root) { - __stream_ = ::FindFirstFile(root.c_str(), &__data_); + __stream_ = ::FindFirstFileEx(root.c_str(), &__data_); if (__stream_ == INVALID_HANDLE_VALUE) { ec = error_code(::GetLastError(), std::generic_category()); const bool ignore_permission_denied = @@ -97,7 +128,14 @@ public: while (::FindNextFile(__stream_, &__data_)) { if (!strcmp(__data_.cFileName, ".") || strcmp(__data_.cFileName, "..")) continue; - __entry_.assign(__root_ / __data_.cFileName); + // FIXME: Cache more of this + //directory_entry::__cached_data cdata; + //cdata.__type_ = get_file_type(__data_); + //cdata.__size_ = get_file_size(__data_); + //cdata.__write_time_ = get_write_time(__data_); + __entry_.__assign_iter_entry( + __root_ / __data_.cFileName, + directory_entry::__create_iter_result(get_file_type(__data))); return true; } ec = error_code(::GetLastError(), std::generic_category()); @@ -157,15 +195,18 @@ public: bool advance(error_code &ec) { while (true) { - auto str = detail::posix_readdir(__stream_, ec); + auto str_type_pair = detail::posix_readdir(__stream_, ec); + auto& str = str_type_pair.first; if (str == "." || str == "..") { continue; } else if (ec || str.empty()) { close(); return false; } else { - __entry_.assign(__root_ / str); - return true; + __entry_.__assign_iter_entry( + __root_ / str, + directory_entry::__create_iter_result(str_type_pair.second)); + return true; } } } diff --git a/src/experimental/filesystem/filesystem_time_helper.h b/src/experimental/filesystem/filesystem_common.h similarity index 58% rename from src/experimental/filesystem/filesystem_time_helper.h rename to src/experimental/filesystem/filesystem_common.h index a60fdef5f..ab7ecbd01 100644 --- a/src/experimental/filesystem/filesystem_time_helper.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===//// -#ifndef FILESYSTEM_TIME_HELPER_H -#define FILESYSTEM_TIME_HELPER_H +#ifndef FILESYSTEM_COMMON_H +#define FILESYSTEM_COMMON_H #include "experimental/__config" #include "chrono" @@ -17,13 +17,77 @@ #include #include +#include +#include /* values for fchmodat */ + +#include + +#if (__APPLE__) +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101300 +#define _LIBCXX_USE_UTIMENSAT +#endif +#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 110000 +#define _LIBCXX_USE_UTIMENSAT +#endif +#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 110000 +#define _LIBCXX_USE_UTIMENSAT +#endif +#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 40000 +#define _LIBCXX_USE_UTIMENSAT +#endif +#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ +#else +// We can use the presence of UTIME_OMIT to detect platforms that provide +// utimensat. +#if defined(UTIME_OMIT) +#define _LIBCXX_USE_UTIMENSAT +#endif +#endif // __APPLE__ + +#if !defined(_LIBCXX_USE_UTIMENSAT) +#include // for ::utimes as used in __last_write_time +#endif + #if !defined(UTIME_OMIT) #include // for ::utimes as used in __last_write_time #endif +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM -namespace time_detail { namespace { +namespace detail { +namespace { + +std::error_code capture_errno() { + _LIBCPP_ASSERT(errno, "Expected errno to be non-zero"); + return std::error_code(errno, std::generic_category()); +} + +void set_or_throw(std::error_code const& m_ec, std::error_code* ec, + const char* msg, path const& p = {}, path const& p2 = {}) { + if (ec) { + *ec = m_ec; + } else { + string msg_s("std::experimental::filesystem::"); + msg_s += msg; + __throw_filesystem_error(msg_s, p, p2, m_ec); + } +} + +void set_or_throw(std::error_code* ec, const char* msg, path const& p = {}, + path const& p2 = {}) { + return set_or_throw(capture_errno(), ec, msg, p, p2); +} + +namespace time_util { using namespace chrono; @@ -78,9 +142,8 @@ const long long fs_time_util_base::min_seconds = template const long long fs_time_util_base::min_nsec_timespec = - duration_cast((FileTimeT::duration::min() - - seconds(min_seconds)) + - seconds(1)) + duration_cast( + (FileTimeT::duration::min() - seconds(min_seconds)) + seconds(1)) .count(); template @@ -145,7 +208,6 @@ public: template static bool set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) { - using namespace chrono; auto dur = tp.time_since_epoch(); auto sec_dur = duration_cast(dur); auto subsec_dur = duration_cast(dur - sec_dur); @@ -163,11 +225,72 @@ public: } }; -} // end namespace -} // end namespace time_detail +} // namespace time_util -using time_detail::fs_time_util; + +using TimeSpec = struct timespec; +using StatT = struct stat; + +using FSTime = time_util::fs_time_util; + +#if defined(__APPLE__) +TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; } +TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; } +#else +TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } +TimeSpec extract_atime(StatT const& st) { return st.st_atim; } +#endif + +#if !defined(_LIBCXX_USE_UTIMENSAT) +using TimeStruct = struct ::timeval; +using TimeStructArray = TimeStruct[2]; +#else +using TimeStruct = struct ::timespec; +using TimeStructArray = TimeStruct[2]; +#endif + +bool SetFileTimes(const path& p, TimeStructArray const& TS, + std::error_code& ec) { +#if !defined(_LIBCXX_USE_UTIMENSAT) + if (::utimes(p.c_str(), TS) == -1) +#else + if (::utimensat(AT_FDCWD, p.c_str(), TS, 0) == -1) +#endif + { + ec = capture_errno(); + return true; + } + return false; +} + +void SetTimeStructTo(TimeStruct& TS, TimeSpec ToTS) { + using namespace chrono; + TS.tv_sec = ToTS.tv_sec; +#if !defined(_LIBCXX_USE_UTIMENSAT) + TS.tv_usec = duration_cast(nanoseconds(ToTS.tv_nsec)).count(); +#else + TS.tv_nsec = ToTS.tv_nsec; +#endif +} + +bool SetTimeStructTo(TimeStruct& TS, file_time_type NewTime) { + using namespace chrono; +#if !defined(_LIBCXX_USE_UTIMENSAT) + return !FSTime::set_times_checked(&TS.tv_sec, &TS.tv_usec, + NewTime); +#else + return !FSTime::set_times_checked(&TS.tv_sec, &TS.tv_nsec, + NewTime); +#endif +} + +} // namespace +} // end namespace detail _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM -#endif // FILESYSTEM_TIME_HELPER_H +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +#endif // FILESYSTEM_COMMON_H diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index 70284ab65..449b60975 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -17,42 +17,18 @@ #include "cstdlib" #include "climits" -#include "filesystem_time_helper.h" +#include "filesystem_common.h" #include #include #include #include /* values for fchmodat */ +#include -#if (__APPLE__) -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101300 -#define _LIBCXX_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 110000 -#define _LIBCXX_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 110000 -#define _LIBCXX_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 40000 -#define _LIBCXX_USE_UTIMENSAT -#endif -#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ -#else -// We can use the presence of UTIME_OMIT to detect platforms that provide -// utimensat. -#if defined(UTIME_OMIT) -#define _LIBCXX_USE_UTIMENSAT -#endif -#endif // __APPLE__ - -#if !defined(_LIBCXX_USE_UTIMENSAT) -#include // for ::utimes as used in __last_write_time +#ifdef NDEBUG +#undef NDEBUG #endif +#include _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM @@ -310,96 +286,78 @@ namespace detail { namespace { using value_type = path::value_type; using string_type = path::string_type; -inline std::error_code capture_errno() { - _LIBCPP_ASSERT(errno, "Expected errno to be non-zero"); - return std::error_code(errno, std::generic_category()); -} - -void set_or_throw(std::error_code const& m_ec, std::error_code* ec, - const char* msg, path const& p = {}, path const& p2 = {}) -{ - if (ec) { - *ec = m_ec; - } else { - string msg_s("std::experimental::filesystem::"); - msg_s += msg; - __throw_filesystem_error(msg_s, p, p2, m_ec); - } -} - -void set_or_throw(std::error_code* ec, const char* msg, - path const& p = {}, path const& p2 = {}) -{ - return set_or_throw(capture_errno(), ec, msg, p, p2); -} - -perms posix_get_perms(const struct ::stat & st) noexcept { - return static_cast(st.st_mode) & perms::mask; +perms posix_get_perms(const struct ::stat& st) noexcept { + return static_cast(st.st_mode) & perms::mask; } ::mode_t posix_convert_perms(perms prms) { - return static_cast< ::mode_t>(prms & perms::mask); + return static_cast< ::mode_t>(prms & perms::mask); } file_status create_file_status(std::error_code& m_ec, path const& p, - struct ::stat& path_stat, - std::error_code* ec) -{ - if (ec) *ec = m_ec; - if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { - return file_status(file_type::not_found); - } - else if (m_ec) { - set_or_throw(m_ec, ec, "posix_stat", p); - return file_status(file_type::none); - } - // else - - file_status fs_tmp; - auto const mode = path_stat.st_mode; - if (S_ISLNK(mode)) fs_tmp.type(file_type::symlink); - else if (S_ISREG(mode)) fs_tmp.type(file_type::regular); - else if (S_ISDIR(mode)) fs_tmp.type(file_type::directory); - else if (S_ISBLK(mode)) fs_tmp.type(file_type::block); - else if (S_ISCHR(mode)) fs_tmp.type(file_type::character); - else if (S_ISFIFO(mode)) fs_tmp.type(file_type::fifo); - else if (S_ISSOCK(mode)) fs_tmp.type(file_type::socket); - else fs_tmp.type(file_type::unknown); - - fs_tmp.permissions(detail::posix_get_perms(path_stat)); - return fs_tmp; -} - -file_status posix_stat(path const & p, struct ::stat& path_stat, - std::error_code* ec) -{ - std::error_code m_ec; - if (::stat(p.c_str(), &path_stat) == -1) - m_ec = detail::capture_errno(); - return create_file_status(m_ec, p, path_stat, ec); + struct ::stat& path_stat, std::error_code* ec) { + if (ec) + *ec = m_ec; + // assert(m_ec.value() != ENOTDIR); + if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { + return file_status(file_type::not_found); + } else if (m_ec) { + set_or_throw(m_ec, ec, "posix_stat", p); + return file_status(file_type::none); + } + // else + + file_status fs_tmp; + auto const mode = path_stat.st_mode; + if (S_ISLNK(mode)) + fs_tmp.type(file_type::symlink); + else if (S_ISREG(mode)) + fs_tmp.type(file_type::regular); + else if (S_ISDIR(mode)) + fs_tmp.type(file_type::directory); + else if (S_ISBLK(mode)) + fs_tmp.type(file_type::block); + else if (S_ISCHR(mode)) + fs_tmp.type(file_type::character); + else if (S_ISFIFO(mode)) + fs_tmp.type(file_type::fifo); + else if (S_ISSOCK(mode)) + fs_tmp.type(file_type::socket); + else + fs_tmp.type(file_type::unknown); + + fs_tmp.permissions(detail::posix_get_perms(path_stat)); + return fs_tmp; +} + +file_status posix_stat(path const& p, struct ::stat& path_stat, + std::error_code* ec) { + std::error_code m_ec; + if (::stat(p.c_str(), &path_stat) == -1) + m_ec = detail::capture_errno(); + return create_file_status(m_ec, p, path_stat, ec); } -file_status posix_stat(path const & p, std::error_code* ec) { - struct ::stat path_stat; - return posix_stat(p, path_stat, ec); +file_status posix_stat(path const& p, std::error_code* ec) { + struct ::stat path_stat; + return posix_stat(p, path_stat, ec); } -file_status posix_lstat(path const & p, struct ::stat & path_stat, - std::error_code* ec) -{ - std::error_code m_ec; - if (::lstat(p.c_str(), &path_stat) == -1) - m_ec = detail::capture_errno(); - return create_file_status(m_ec, p, path_stat, ec); +file_status posix_lstat(path const& p, struct ::stat& path_stat, + std::error_code* ec) { + std::error_code m_ec; + if (::lstat(p.c_str(), &path_stat) == -1) + m_ec = detail::capture_errno(); + return create_file_status(m_ec, p, path_stat, ec); } -file_status posix_lstat(path const & p, std::error_code* ec) { - struct ::stat path_stat; - return posix_lstat(p, path_stat, ec); +file_status posix_lstat(path const& p, std::error_code* ec) { + struct ::stat path_stat; + return posix_lstat(p, path_stat, ec); } bool stat_equivalent(struct ::stat& st1, struct ::stat& st2) { - return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); + return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); } // DETAIL::MISC @@ -622,7 +580,6 @@ void __copy_symlink(const path& existing_symlink, const path& new_symlink, __create_symlink(real_path, new_symlink, ec); } - bool __create_directories(const path& p, std::error_code *ec) { std::error_code m_ec; @@ -755,10 +712,12 @@ std::uintmax_t __file_size(const path& p, std::error_code *ec) struct ::stat st; file_status fst = detail::posix_stat(p, st, &m_ec); if (!exists(fst) || !is_regular_file(fst)) { - if (!m_ec) - m_ec = make_error_code(errc::not_supported); - set_or_throw(m_ec, ec, "file_size", p); - return static_cast(-1); + errc error_kind = + is_directory(fst) ? errc::is_a_directory : errc::not_supported; + if (!m_ec) + m_ec = make_error_code(error_kind); + set_or_throw(m_ec, ec, "file_size", p); + return static_cast(-1); } // is_regular_file(p) == true if (ec) ec->clear(); @@ -806,25 +765,18 @@ bool __fs_is_empty(const path& p, std::error_code *ec) _LIBCPP_UNREACHABLE(); } - -namespace detail { namespace { - -using TimeSpec = struct timespec; -using StatT = struct stat; - -#if defined(__APPLE__) -TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; } -__attribute__((unused)) // Suppress warning -TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; } -#else -TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } -__attribute__((unused)) // Suppress warning -TimeSpec extract_atime(StatT const& st) { return st.st_atim; } -#endif - -}} // end namespace detail - -using FSTime = fs_time_util; +static file_time_type __extract_last_write_time(path const& p, + const struct ::stat& st, + error_code *ec) { + using detail::FSTime; + auto ts = detail::extract_mtime(st); + if (!FSTime::is_representable(ts)) { + set_or_throw(make_error_code(errc::value_too_large), ec, "last_write_time", + p); + return file_time_type::min(); + } + return FSTime::convert_timespec(ts); +} file_time_type __last_write_time(const path& p, std::error_code *ec) { @@ -837,21 +789,17 @@ file_time_type __last_write_time(const path& p, std::error_code *ec) return file_time_type::min(); } if (ec) ec->clear(); - auto ts = detail::extract_mtime(st); - if (!FSTime::is_representable(ts)) { - set_or_throw(error_code(EOVERFLOW, generic_category()), ec, - "last_write_time", p); - return file_time_type::min(); - } - return FSTime::convert_timespec(ts); + return __extract_last_write_time(p, st, ec); } void __last_write_time(const path& p, file_time_type new_time, std::error_code *ec) { using namespace std::chrono; - std::error_code m_ec; + using namespace detail; + std::error_code m_ec; + TimeStructArray tbuf; #if !defined(_LIBCXX_USE_UTIMENSAT) // This implementation has a race condition between determining the // last access time and attempting to set it to the same value using @@ -862,37 +810,18 @@ void __last_write_time(const path& p, file_time_type new_time, set_or_throw(m_ec, ec, "last_write_time", p); return; } - auto atime = detail::extract_atime(st); - struct ::timeval tbuf[2]; - tbuf[0].tv_sec = atime.tv_sec; - tbuf[0].tv_usec = duration_cast(nanoseconds(atime.tv_nsec)).count(); - const bool overflowed = !FSTime::set_times_checked( - &tbuf[1].tv_sec, &tbuf[1].tv_usec, new_time); - - if (overflowed) { - set_or_throw(make_error_code(errc::invalid_argument), ec, - "last_write_time", p); - return; - } - if (::utimes(p.c_str(), tbuf) == -1) { - m_ec = detail::capture_errno(); - } + SetTimeStructTo(tbuf[0], detail::extract_atime(st)); #else - struct ::timespec tbuf[2]; tbuf[0].tv_sec = 0; tbuf[0].tv_nsec = UTIME_OMIT; - - const bool overflowed = !FSTime::set_times_checked( - &tbuf[1].tv_sec, &tbuf[1].tv_nsec, new_time); - if (overflowed) { - set_or_throw(make_error_code(errc::invalid_argument), - ec, "last_write_time", p); - return; - } - if (::utimensat(AT_FDCWD, p.c_str(), tbuf, 0) == -1) { - m_ec = detail::capture_errno(); - } #endif + if (SetTimeStructTo(tbuf[1], new_time)) { + set_or_throw(make_error_code(errc::invalid_argument), ec, + "last_write_time", p); + return; + } + + SetFileTimes(p, tbuf, m_ec); if (m_ec) set_or_throw(m_ec, ec, "last_write_time", p); else if (ec) @@ -1116,8 +1045,6 @@ path __weakly_canonical(const path& p, std::error_code *ec) { return result.lexically_normal(); } - - /////////////////////////////////////////////////////////////////////////////// // path definitions /////////////////////////////////////////////////////////////////////////////// @@ -1468,5 +1395,105 @@ path::iterator& path::iterator::__decrement() { return *this; } +/////////////////////////////////////////////////////////////////////////////// +// directory entry definitions +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _LIBCPP_WIN32API +error_code directory_entry::__do_refresh() noexcept { + __data_.__reset(); + error_code failure_ec; + + struct ::stat full_st; + file_status st = detail::posix_lstat(__p_, full_st, &failure_ec); + if (!status_known(st)) { + __data_.__reset(); + return failure_ec; + } + + if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) { + __data_.__cache_type_ = directory_entry::_RefreshNonSymlink; + __data_.__type_ = st.type(); + __data_.__non_sym_perms_ = st.permissions(); + } else { // we have a symlink + __data_.__sym_perms_ = st.permissions(); + // Get the information about the linked entity. + // Ignore errors from stat, since we don't want errors regarding symlink + // resolution to be reported to the user. + error_code ignored_ec; + st = detail::posix_stat(__p_, full_st, &ignored_ec); + + __data_.__type_ = st.type(); + __data_.__non_sym_perms_ = st.permissions(); + + // If we failed to resolve the link, then only partially populate the + // cache. + if (!status_known(st)) { + __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; + return error_code{}; + } + // Otherwise, we resolved the link as not existing. That's OK. + __data_.__cache_type_ = directory_entry::_RefreshSymlink; + } + + if (_VSTD_FS::is_regular_file(st)) + __data_.__size_ = static_cast(full_st.st_size); + + if (_VSTD_FS::exists(st)) { + __data_.__nlink_ = static_cast(full_st.st_nlink); + + // Attempt to extract the mtime, and fail if it's not representable using + // file_time_type. For now we ignore the error, as we'll report it when + // the value is actually used. + error_code ignored_ec; + __data_.__write_time_ = + __extract_last_write_time(__p_, full_st, &ignored_ec); + } + + return failure_ec; +} +#else +error_code directory_entry::__do_refresh() noexcept { + __data_.__reset(); + error_code failure_ec; + + file_status st = _VSTD_FS::symlink_status(__p_, failure_ec); + if (!status_known(st)) { + __data_.__reset(); + return failure_ec; + } + + if (!_VSTD_FS::exists(st) || !_VSTD_FS::is_symlink(st)) { + __data_.__cache_type_ = directory_entry::_RefreshNonSymlink; + __data_.__type_ = st.type(); + __data_.__non_sym_perms_ = st.permissions(); + } else { // we have a symlink + __data_.__sym_perms_ = st.permissions(); + // Get the information about the linked entity. + // Ignore errors from stat, since we don't want errors regarding symlink + // resolution to be reported to the user. + error_code ignored_ec; + st = _VSTD_FS::status(__p_, ignored_ec); + + __data_.__type_ = st.type(); + __data_.__non_sym_perms_ = st.permissions(); + + // If we failed to resolve the link, then only partially populate the + // cache. + if (!status_known(st)) { + __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; + return error_code{}; + } + // Otherwise, we resolved the link as not existing. That's OK. + __data_.__cache_type_ = directory_entry::_RefreshSymlink; + } + + // FIXME: This is currently broken, and the implementation only a placeholder. + // We need to cache last_write_time, file_size, and hard_link_count here before + // the implementation actually works. + + return failure_ec; +} +#endif _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM diff --git a/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp b/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp new file mode 100644 index 000000000..30b44b877 --- /dev/null +++ b/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// RUN: %build -I%libcxx_src_root/src/experimental/filesystem +// RUN: %run + +#include "filesystem_include.hpp" +#include +#include + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +#include "filesystem_common.h" + +using namespace fs::detail; + +TEST_SUITE(directory_entry_mods_suite) + +TEST_CASE(last_write_time_not_representable_error) { + using namespace fs; + using namespace std::chrono; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + + TimeSpec ToTime; + ToTime.tv_sec = std::numeric_limits::max(); + ToTime.tv_nsec = duration_cast(seconds(1)).count() - 1; + + TimeStructArray TS; + SetTimeStructTo(TS[0], ToTime); + SetTimeStructTo(TS[1], ToTime); + + file_time_type old_time = last_write_time(file); + directory_entry ent(file); + + file_time_type start_time = file_time_type::clock::now() - hours(1); + last_write_time(file, start_time); + + TEST_CHECK(ent.last_write_time() == old_time); + + bool IsRepresentable = true; + file_time_type rep_value; + { + std::error_code ec; + if (SetFileTimes(file, TS, ec)) { + TEST_REQUIRE(false && "unsupported"); + } + ec.clear(); + rep_value = last_write_time(file, ec); + IsRepresentable = !bool(ec); + } + + if (!IsRepresentable) { + std::error_code rec = GetTestEC(); + ent.refresh(rec); + TEST_CHECK(!rec); + + const std::errc expected_err = std::errc::value_too_large; + + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == file_time_type::min()); + TEST_CHECK(ErrorIs(ec, expected_err)); + + ec = GetTestEC(); + TEST_CHECK(last_write_time(file, ec) == file_time_type::min()); + TEST_CHECK(ErrorIs(ec, expected_err)); + + ExceptionChecker CheckExcept(file, expected_err); + TEST_CHECK_THROW_RESULT(fs::filesystem_error, CheckExcept, + ent.last_write_time()); + + } else { + ent.refresh(); + + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == rep_value); + TEST_CHECK(!ec); + } +} + +TEST_SUITE_END() diff --git a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp b/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp index 972d51813..e418851d9 100644 --- a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp +++ b/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp @@ -23,12 +23,12 @@ #include #include -#include "filesystem_time_helper.h" +#include "filesystem_common.h" using namespace std::chrono; namespace fs = std::experimental::filesystem; using fs::file_time_type; -using fs::fs_time_util; +using fs::detail::fs_time_util; enum TestKind { TK_64Bit, TK_32Bit, TK_FloatingPoint }; diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons.pass.cpp deleted file mode 100644 index 8a9a1b5d3..000000000 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons.pass.cpp +++ /dev/null @@ -1,96 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03 - -// - -// class directory_entry - -// directory_entry() noexcept = default; -// directory_entry(const directory_entry&) = default; -// directory_entry(directory_entry&&) noexcept = default; -// explicit directory_entry(const path); - -#include "filesystem_include.hpp" -#include -#include - - -void test_default_ctor() -{ - using namespace fs; - // Default - { - static_assert(std::is_nothrow_default_constructible::value, - "directory_entry must have a nothrow default constructor"); - directory_entry e; - assert(e.path() == path()); - } -} - - -void test_copy_ctor() -{ - using namespace fs; - // Copy - { - static_assert(std::is_copy_constructible::value, - "directory_entry must be copy constructible"); - static_assert(!std::is_nothrow_copy_constructible::value, - "directory_entry's copy constructor cannot be noexcept"); - const path p("foo/bar/baz"); - const directory_entry e(p); - assert(e.path() == p); - directory_entry e2(e); - assert(e.path() == p); - assert(e2.path() == p); - } - -} - -void test_move_ctor() -{ - using namespace fs; - // Move - { - static_assert(std::is_nothrow_move_constructible::value, - "directory_entry must be nothrow move constructible"); - const path p("foo/bar/baz"); - directory_entry e(p); - assert(e.path() == p); - directory_entry e2(std::move(e)); - assert(e2.path() == p); - assert(e.path() != p); // Testing moved from state. - } -} - -void test_path_ctor() { - using namespace fs; - { - static_assert(std::is_constructible::value, - "directory_entry must be constructible from path"); - static_assert(!std::is_nothrow_constructible::value, - "directory_entry constructor should not be noexcept"); - static_assert(!std::is_convertible::value, - "directory_entry constructor should be explicit"); - } - { - const path p("foo/bar/baz"); - const directory_entry e(p); - assert(p == e.path()); - } -} - -int main() { - test_default_ctor(); - test_copy_ctor(); - test_move_ctor(); - test_path_ctor(); -} diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy.pass.cpp new file mode 100644 index 000000000..f46302938 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy.pass.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// directory_entry(const directory_entry&) = default; + +#include "filesystem_include.hpp" +#include +#include + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" +#include "test_convertible.hpp" + +TEST_SUITE(directory_entry_path_ctor_suite) + +TEST_CASE(copy_ctor) { + using namespace fs; + // Copy + { + static_assert(std::is_copy_constructible::value, + "directory_entry must be copy constructible"); + static_assert(!std::is_nothrow_copy_constructible::value, + "directory_entry's copy constructor cannot be noexcept"); + const path p("foo/bar/baz"); + const directory_entry e(p); + assert(e.path() == p); + directory_entry e2(e); + assert(e.path() == p); + assert(e2.path() == p); + } +} + +TEST_CASE(copy_ctor_copies_cache) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path sym = env.create_symlink("dir/file", "sym"); + + { + directory_entry ent(sym); + + fs::remove(sym); + + directory_entry ent_cp(ent); + TEST_CHECK(ent_cp.path() == sym); + TEST_CHECK(ent_cp.is_symlink()); + } + + { + directory_entry ent(file); + + fs::remove(file); + + directory_entry ent_cp(ent); + TEST_CHECK(ent_cp.path() == file); + TEST_CHECK(ent_cp.is_regular_file()); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp new file mode 100644 index 000000000..447d40985 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp @@ -0,0 +1,82 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// directory_entry& operator=(directory_entry const&) = default; +// directory_entry& operator=(directory_entry&&) noexcept = default; +// void assign(path const&); +// void replace_filename(path const&); + +#include "filesystem_include.hpp" +#include +#include + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +TEST_SUITE(directory_entry_ctor_suite) + +TEST_CASE(test_copy_assign_operator) { + using namespace fs; + // Copy + { + static_assert(std::is_copy_assignable::value, + "directory_entry must be copy assignable"); + static_assert(!std::is_nothrow_copy_assignable::value, + "directory_entry's copy assignment cannot be noexcept"); + const path p("foo/bar/baz"); + const path p2("abc"); + const directory_entry e(p); + directory_entry e2; + assert(e.path() == p && e2.path() == path()); + e2 = e; + assert(e.path() == p && e2.path() == p); + directory_entry e3(p2); + e2 = e3; + assert(e2.path() == p2 && e3.path() == p2); + } +} + +TEST_CASE(copy_assign_copies_cache) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path sym = env.create_symlink("dir/file", "sym"); + + { + directory_entry ent(sym); + + fs::remove(sym); + + directory_entry ent_cp; + ent_cp = ent; + TEST_CHECK(ent_cp.path() == sym); + TEST_CHECK(ent_cp.is_symlink()); + } + + { + directory_entry ent(file); + + fs::remove(file); + + directory_entry ent_cp; + ent_cp = ent; + TEST_CHECK(ent_cp.path() == file); + TEST_CHECK(ent_cp.is_regular_file()); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default.pass.cpp new file mode 100644 index 000000000..dd4543dbb --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// directory_entry() noexcept = default; + +#include "filesystem_include.hpp" +#include +#include + +int main() { + using namespace fs; + // Default + { + static_assert(std::is_nothrow_default_constructible::value, + "directory_entry must have a nothrow default constructor"); + directory_entry e; + assert(e.path() == path()); + } +} diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move.pass.cpp new file mode 100644 index 000000000..f22bf1c33 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// directory_entry(directory_entry&&) noexcept = default; + +#include "filesystem_include.hpp" +#include +#include + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" +#include "test_convertible.hpp" + +TEST_SUITE(directory_entry_path_ctor_suite) + +TEST_CASE(move_ctor) { + using namespace fs; + // Move + { + static_assert(std::is_nothrow_move_constructible::value, + "directory_entry must be nothrow move constructible"); + const path p("foo/bar/baz"); + directory_entry e(p); + assert(e.path() == p); + directory_entry e2(std::move(e)); + assert(e2.path() == p); + assert(e.path() != p); // Testing moved from state. + } +} + +TEST_CASE(move_ctor_copies_cache) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path sym = env.create_symlink("dir/file", "sym"); + + { + directory_entry ent(sym); + + fs::remove(sym); + + directory_entry ent_cp(std::move(ent)); + TEST_CHECK(ent_cp.path() == sym); + TEST_CHECK(ent_cp.is_symlink()); + } + + { + directory_entry ent(file); + + fs::remove(file); + + directory_entry ent_cp(std::move(ent)); + TEST_CHECK(ent_cp.path() == file); + TEST_CHECK(ent_cp.is_regular_file()); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move_assign.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move_assign.pass.cpp new file mode 100644 index 000000000..abd9bc865 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move_assign.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// directory_entry& operator=(directory_entry const&) = default; +// directory_entry& operator=(directory_entry&&) noexcept = default; +// void assign(path const&); +// void replace_filename(path const&); + +#include "filesystem_include.hpp" +#include +#include + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +TEST_SUITE(directory_entry_ctor_suite) + +TEST_CASE(test_move_assign_operator) { + using namespace fs; + // Copy + { + static_assert(std::is_nothrow_move_assignable::value, + "directory_entry is noexcept move assignable"); + const path p("foo/bar/baz"); + const path p2("abc"); + directory_entry e(p); + directory_entry e2(p2); + assert(e.path() == p && e2.path() == p2); + e2 = std::move(e); + assert(e2.path() == p); + assert(e.path() != p); // testing moved from state + } +} + +TEST_CASE(move_assign_copies_cache) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path sym = env.create_symlink("dir/file", "sym"); + + { + directory_entry ent(sym); + + fs::remove(sym); + + directory_entry ent_cp; + ent_cp = std::move(ent); + TEST_CHECK(ent_cp.path() == sym); + TEST_CHECK(ent_cp.is_symlink()); + } + + { + directory_entry ent(file); + + fs::remove(file); + + directory_entry ent_cp; + ent_cp = std::move(ent); + TEST_CHECK(ent_cp.path() == file); + TEST_CHECK(ent_cp.is_regular_file()); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/path.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/path.pass.cpp new file mode 100644 index 000000000..b6ecd3f58 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/path.pass.cpp @@ -0,0 +1,182 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// explicit directory_entry(const path); +// directory_entry(const path&, error_code& ec); + +#include "filesystem_include.hpp" +#include +#include + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" +#include "test_convertible.hpp" + +TEST_SUITE(directory_entry_path_ctor_suite) + +TEST_CASE(path_ctor) { + using namespace fs; + { + static_assert(std::is_constructible::value, + "directory_entry must be constructible from path"); + static_assert( + !std::is_nothrow_constructible::value, + "directory_entry constructor should not be noexcept"); + static_assert(!std::is_convertible::value, + "directory_entry constructor should be explicit"); + } + { + const path p("foo/bar/baz"); + const directory_entry e(p); + TEST_CHECK(e.path() == p); + } +} + +TEST_CASE(path_ec_ctor) { + using namespace fs; + { + static_assert( + std::is_constructible::value, + "directory_entry must be constructible from path and error_code"); + static_assert(!std::is_nothrow_constructible::value, + "directory_entry constructor should not be noexcept"); + static_assert( + test_convertible(), + "directory_entry constructor should not be explicit"); + } + { + std::error_code ec = GetTestEC(); + const directory_entry e(StaticEnv::File, ec); + TEST_CHECK(e.path() == StaticEnv::File); + TEST_CHECK(!ec); + } + { + const path p("foo/bar/baz"); + std::error_code ec = GetTestEC(); + const directory_entry e(p, ec); + TEST_CHECK(e.path() == p); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + } +} + +TEST_CASE(path_ctor_calls_refresh) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path sym = env.create_symlink("dir/file", "sym"); + + { + directory_entry ent(file); + std::error_code ec = GetTestEC(); + directory_entry ent_ec(file, ec); + TEST_CHECK(!ec); + + LIBCPP_ONLY(remove(file)); + + TEST_CHECK(ent.exists()); + TEST_CHECK(ent_ec.exists()); + + TEST_CHECK(ent.file_size() == 42); + TEST_CHECK(ent_ec.file_size() == 42); + } + + env.create_file("dir/file", 101); + + { + directory_entry ent(sym); + std::error_code ec = GetTestEC(); + directory_entry ent_ec(sym, ec); + TEST_CHECK(!ec); + + LIBCPP_ONLY(remove(file)); + LIBCPP_ONLY(remove(sym)); + + TEST_CHECK(ent.is_symlink()); + TEST_CHECK(ent_ec.is_symlink()); + + TEST_CHECK(ent.is_regular_file()); + TEST_CHECK(ent_ec.is_regular_file()); + + TEST_CHECK(ent.file_size() == 101); + TEST_CHECK(ent_ec.file_size() == 101); + } +} + +TEST_CASE(path_ctor_dne) { + using namespace fs; + + { + std::error_code ec = GetTestEC(); + directory_entry ent(StaticEnv::DNE, ec); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + TEST_CHECK(ent.path() == StaticEnv::DNE); + } + // don't report dead symlinks as an error. + { + std::error_code ec = GetTestEC(); + directory_entry ent(StaticEnv::BadSymlink, ec); + TEST_CHECK(!ec); + TEST_CHECK(ent.path() == StaticEnv::BadSymlink); + } + // DNE does not cause the constructor to throw + { + directory_entry ent(StaticEnv::DNE); + TEST_CHECK(ent.path() == StaticEnv::DNE); + + directory_entry ent_two(StaticEnv::BadSymlink); + TEST_CHECK(ent_two.path() == StaticEnv::BadSymlink); + } +} + +TEST_CASE(path_ctor_cannot_resolve) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path file_out_of_dir = env.create_file("file1", 101); + const path sym_out_of_dir = env.create_symlink("dir/file", "sym"); + const path sym_in_dir = env.create_symlink("dir/file1", "dir/sym2"); + permissions(dir, perms::none); + + { + std::error_code ec = GetTestEC(); + directory_entry ent(file, ec); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + TEST_CHECK(ent.path() == file); + } + { + std::error_code ec = GetTestEC(); + directory_entry ent(sym_in_dir, ec); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + TEST_CHECK(ent.path() == sym_in_dir); + } + { + std::error_code ec = GetTestEC(); + directory_entry ent(sym_out_of_dir, ec); + TEST_CHECK(!ec); + TEST_CHECK(ent.path() == sym_out_of_dir); + } + { + TEST_CHECK_NO_THROW(directory_entry(file)); + TEST_CHECK_NO_THROW(directory_entry(sym_in_dir)); + TEST_CHECK_NO_THROW(directory_entry(sym_out_of_dir)); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods.pass.cpp deleted file mode 100644 index 13428db19..000000000 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods.pass.cpp +++ /dev/null @@ -1,112 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03 - -// - -// class directory_entry - -// directory_entry& operator=(directory_entry const&) = default; -// directory_entry& operator=(directory_entry&&) noexcept = default; -// void assign(path const&); -// void replace_filename(path const&); - -#include "filesystem_include.hpp" -#include -#include - - -void test_copy_assign_operator() -{ - using namespace fs; - // Copy - { - static_assert(std::is_copy_assignable::value, - "directory_entry must be copy assignable"); - static_assert(!std::is_nothrow_copy_assignable::value, - "directory_entry's copy assignment cannot be noexcept"); - const path p("foo/bar/baz"); - const path p2("abc"); - const directory_entry e(p); - directory_entry e2; - assert(e.path() == p && e2.path() == path()); - e2 = e; - assert(e.path() == p && e2.path() == p); - directory_entry e3(p2); - e2 = e3; - assert(e2.path() == p2 && e3.path() == p2); - } -} - - -void test_move_assign_operator() -{ - using namespace fs; - // Copy - { - static_assert(std::is_nothrow_move_assignable::value, - "directory_entry is noexcept move assignable"); - const path p("foo/bar/baz"); - const path p2("abc"); - directory_entry e(p); - directory_entry e2(p2); - assert(e.path() == p && e2.path() == p2); - e2 = std::move(e); - assert(e2.path() == p); - assert(e.path() != p); // testing moved from state - } -} - -void test_path_assign_method() -{ - using namespace fs; - const path p("foo/bar/baz"); - const path p2("abc"); - directory_entry e(p); - { - static_assert(std::is_same::value, - "return type should be void"); - static_assert(noexcept(e.assign(p)) == false, "operation must not be noexcept"); - } - { - assert(e.path() == p); - e.assign(p2); - assert(e.path() == p2 && e.path() != p); - e.assign(p); - assert(e.path() == p && e.path() != p2); - } -} - -void test_replace_filename_method() -{ - using namespace fs; - const path p("/path/to/foo.exe"); - const path replace("bar.out"); - const path expect("/path/to/bar.out"); - directory_entry e(p); - { - static_assert(noexcept(e.replace_filename(replace)) == false, - "operation cannot be noexcept"); - static_assert(std::is_same::value, - "operation must return void"); - } - { - assert(e.path() == p); - e.replace_filename(replace); - assert(e.path() == expect); - } -} - -int main() { - test_copy_assign_operator(); - test_move_assign_operator(); - test_path_assign_method(); - test_replace_filename_method(); -} diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/assign.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/assign.pass.cpp new file mode 100644 index 000000000..70f0de3fb --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/assign.pass.cpp @@ -0,0 +1,132 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// directory_entry& operator=(directory_entry const&) = default; +// directory_entry& operator=(directory_entry&&) noexcept = default; +// void assign(path const&); +// void replace_filename(path const&); + +#include "filesystem_include.hpp" +#include +#include + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +TEST_SUITE(directory_entry_mods_suite) + +TEST_CASE(test_path_assign_method) { + using namespace fs; + const path p("foo/bar/baz"); + const path p2("abc"); + directory_entry e(p); + { + static_assert(std::is_same::value, + "return type should be void"); + static_assert(noexcept(e.assign(p)) == false, + "operation must not be noexcept"); + } + { + TEST_CHECK(e.path() == p); + e.assign(p2); + TEST_CHECK(e.path() == p2 && e.path() != p); + e.assign(p); + TEST_CHECK(e.path() == p && e.path() != p2); + } +} + +TEST_CASE(test_path_assign_ec_method) { + using namespace fs; + const path p("foo/bar/baz"); + const path p2("abc"); + { + std::error_code ec; + directory_entry e(p); + static_assert(std::is_same::value, + "return type should be void"); + static_assert(noexcept(e.assign(p, ec)) == false, + "operation must not be noexcept"); + } + { + directory_entry ent(p); + std::error_code ec = GetTestEC(); + ent.assign(p2, ec); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + TEST_CHECK(ent.path() == p2); + } +} + +TEST_CASE(test_assign_calls_refresh) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path sym = env.create_symlink("dir/file", "sym"); + + { + directory_entry ent; + ent.assign(file); + + // removing the file demonstrates that the values where cached previously. + LIBCPP_ONLY(remove(file)); + + TEST_CHECK(ent.is_regular_file()); + } + env.create_file("dir/file", 101); + { + directory_entry ent; + ent.assign(sym); + + LIBCPP_ONLY(remove(file)); + LIBCPP_ONLY(remove(sym)); + + TEST_CHECK(ent.is_symlink()); + TEST_CHECK(ent.is_regular_file()); + } +} + +TEST_CASE(test_assign_propagates_error) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path sym_out_of_dir = env.create_symlink("dir/file", "sym"); + const path file_out_of_dir = env.create_file("file1"); + const path sym_in_dir = env.create_symlink("file1", "dir/sym1"); + + permissions(dir, perms::none); + + { + directory_entry ent; + std::error_code ec = GetTestEC(); + ent.assign(file, ec); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + } + { + directory_entry ent; + std::error_code ec = GetTestEC(); + ent.assign(sym_in_dir, ec); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + } + { + directory_entry ent; + std::error_code ec = GetTestEC(); + ent.assign(sym_out_of_dir, ec); + TEST_CHECK(!ec); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp new file mode 100644 index 000000000..40d2cef1d --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp @@ -0,0 +1,339 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// directory_entry& operator=(directory_entry const&) = default; +// directory_entry& operator=(directory_entry&&) noexcept = default; +// void assign(path const&); +// void replace_filename(path const&); + +#include "filesystem_include.hpp" +#include +#include + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +TEST_SUITE(directory_entry_mods_suite) + +TEST_CASE(test_refresh_method) { + using namespace fs; + { + directory_entry e; + static_assert(noexcept(e.refresh()) == false, + "operation cannot be noexcept"); + static_assert(std::is_same::value, + "operation must return void"); + } + { + directory_entry e; + e.refresh(); + TEST_CHECK(!e.exists()); + } +} + +TEST_CASE(test_refresh_ec_method) { + using namespace fs; + { + directory_entry e; + std::error_code ec; + static_assert(noexcept(e.refresh(ec)), "operation should be noexcept"); + static_assert(std::is_same::value, + "operation must return void"); + } + { + directory_entry e; + std::error_code ec = GetTestEC(); + e.refresh(ec); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + } +} + +TEST_CASE(refresh_on_file_dne) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + + const perms old_perms = status(dir).permissions(); + + // test file doesn't exist + { + directory_entry ent(file); + remove(file); + TEST_CHECK(ent.exists()); + + ent.refresh(); + + permissions(dir, perms::none); + TEST_CHECK(!ent.exists()); + } + permissions(dir, old_perms); + env.create_file("dir/file", 101); + { + directory_entry ent(file); + remove(file); + TEST_CHECK(ent.exists()); + + std::error_code ec = GetTestEC(); + ent.refresh(ec); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + permissions(dir, perms::none); + TEST_CHECK(!ent.exists()); + } +} + +void remove_if_exists(const fs::path& p) { + std::error_code ec; + remove(p, ec); +} + +TEST_CASE(refresh_on_bad_symlink) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path sym = env.create_symlink("dir/file", "sym"); + + const perms old_perms = status(dir).permissions(); + + // test file doesn't exist + { + directory_entry ent(sym); + LIBCPP_ONLY(remove(file)); + TEST_CHECK(ent.is_symlink()); + TEST_CHECK(ent.is_regular_file()); + TEST_CHECK(ent.exists()); + + remove_if_exists(file); + ent.refresh(); + + LIBCPP_ONLY(permissions(dir, perms::none)); + TEST_CHECK(ent.is_symlink()); + TEST_CHECK(!ent.is_regular_file()); + TEST_CHECK(!ent.exists()); + } + permissions(dir, old_perms); + env.create_file("dir/file", 101); + { + directory_entry ent(sym); + LIBCPP_ONLY(remove(file)); + TEST_CHECK(ent.is_symlink()); + TEST_CHECK(ent.is_regular_file()); + TEST_CHECK(ent.exists()); + + remove_if_exists(file); + + std::error_code ec = GetTestEC(); + ent.refresh(ec); + TEST_CHECK(!ec); // we don't report bad symlinks as an error. + + LIBCPP_ONLY(permissions(dir, perms::none)); + TEST_CHECK(!ent.exists()); + } +} + +TEST_CASE(refresh_cannot_resolve) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path file_out_of_dir = env.create_file("file1", 99); + const path sym_out_of_dir = env.create_symlink("dir/file", "sym"); + const path sym_in_dir = env.create_symlink("file1", "dir/sym1"); + perms old_perms = status(dir).permissions(); + + { + directory_entry ent(file); + permissions(dir, perms::none); + + TEST_CHECK(ent.is_regular_file()); + + std::error_code ec = GetTestEC(); + ent.refresh(ec); + + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + TEST_CHECK(ent.path() == file); + + ExceptionChecker Checker(file, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.refresh()); + } + permissions(dir, old_perms); + { + directory_entry ent(sym_in_dir); + permissions(dir, perms::none); + TEST_CHECK(ent.is_symlink()); + + std::error_code ec = GetTestEC(); + ent.refresh(ec); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + TEST_CHECK(ent.path() == sym_in_dir); + + ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.refresh()); + } + permissions(dir, old_perms); + { + directory_entry ent(sym_out_of_dir); + permissions(dir, perms::none); + TEST_CHECK(ent.is_symlink()); + + // Failure to resolve the linked entity due to permissions is not + // reported as an error. + std::error_code ec = GetTestEC(); + ent.refresh(ec); + TEST_CHECK(!ec); + TEST_CHECK(ent.is_symlink()); + + ec = GetTestEC(); + TEST_CHECK(ent.exists(ec) == false); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + TEST_CHECK(ent.path() == sym_out_of_dir); + } + permissions(dir, old_perms); + { + directory_entry ent_file(file); + directory_entry ent_sym(sym_in_dir); + directory_entry ent_sym2(sym_out_of_dir); + permissions(dir, perms::none); + ((void)ent_file); + ((void)ent_sym); + + TEST_CHECK_THROW(filesystem_error, ent_file.refresh()); + TEST_CHECK_THROW(filesystem_error, ent_sym.refresh()); + TEST_CHECK_NO_THROW(ent_sym2); + } +} + +TEST_CASE(refresh_doesnt_throw_on_dne_but_reports_it) { + using namespace fs; + scoped_test_env env; + + const path file = env.create_file("file1", 42); + const path sym = env.create_symlink("file1", "sym"); + + { + directory_entry ent(file); + TEST_CHECK(ent.file_size() == 42); + + remove(file); + + std::error_code ec = GetTestEC(); + ent.refresh(ec); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + TEST_CHECK_NO_THROW(ent.refresh()); + + ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + // doesn't throw! + TEST_CHECK_THROW(filesystem_error, ent.file_size()); + } + env.create_file("file1", 99); + { + directory_entry ent(sym); + TEST_CHECK(ent.is_symlink()); + TEST_CHECK(ent.is_regular_file()); + TEST_CHECK(ent.file_size() == 99); + + remove(file); + + std::error_code ec = GetTestEC(); + ent.refresh(ec); + TEST_CHECK(!ec); + + ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + TEST_CHECK_THROW(filesystem_error, ent.file_size()); + } +} + +TEST_CASE(access_cache_after_refresh_fails) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path file_out_of_dir = env.create_file("file1", 101); + const path sym = env.create_symlink("dir/file", "sym"); + const path sym_in_dir = env.create_symlink("dir/file", "dir/sym2"); + + const perms old_perms = status(dir).permissions(); + +#define CHECK_ACCESS(func, expect) \ + ec = GetTestEC(); \ + TEST_CHECK(ent.func(ec) == expect); \ + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)) + + // test file doesn't exist + { + directory_entry ent(file); + + TEST_CHECK(!ent.is_symlink()); + TEST_CHECK(ent.is_regular_file()); + TEST_CHECK(ent.exists()); + + permissions(dir, perms::none); + std::error_code ec = GetTestEC(); + ent.refresh(ec); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + CHECK_ACCESS(exists, false); + CHECK_ACCESS(is_symlink, false); + CHECK_ACCESS(last_write_time, file_time_type::min()); + CHECK_ACCESS(hard_link_count, uintmax_t(-1)); + } + permissions(dir, old_perms); + { + directory_entry ent(sym_in_dir); + TEST_CHECK(ent.is_symlink()); + TEST_CHECK(ent.is_regular_file()); + TEST_CHECK(ent.exists()); + + permissions(dir, perms::none); + std::error_code ec = GetTestEC(); + ent.refresh(ec); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + CHECK_ACCESS(exists, false); + CHECK_ACCESS(is_symlink, false); + CHECK_ACCESS(last_write_time, file_time_type::min()); + CHECK_ACCESS(hard_link_count, uintmax_t(-1)); + } + permissions(dir, old_perms); + { + directory_entry ent(sym); + TEST_CHECK(ent.is_symlink()); + TEST_CHECK(ent.is_regular_file()); + TEST_CHECK(ent.exists()); + + permissions(dir, perms::none); + std::error_code ec = GetTestEC(); + ent.refresh(ec); + TEST_CHECK(!ec); + TEST_CHECK(ent.is_symlink()); + + CHECK_ACCESS(exists, false); + CHECK_ACCESS(is_regular_file, false); + CHECK_ACCESS(last_write_time, file_time_type::min()); + CHECK_ACCESS(hard_link_count, uintmax_t(-1)); + } +#undef CHECK_ACCESS +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp new file mode 100644 index 000000000..24b5ebf07 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp @@ -0,0 +1,169 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// directory_entry& operator=(directory_entry const&) = default; +// directory_entry& operator=(directory_entry&&) noexcept = default; +// void assign(path const&); +// void replace_filename(path const&); + +#include "filesystem_include.hpp" +#include +#include + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +TEST_SUITE(directory_entry_mods_suite) + +TEST_CASE(test_replace_filename_method) { + using namespace fs; + + { + directory_entry e; + path replace; + static_assert(noexcept(e.replace_filename(replace)) == false, + "operation cannot be noexcept"); + static_assert( + std::is_same::value, + "operation must return void"); + } + { + const path p("/path/to/foo.exe"); + const path replace("bar.out"); + const path expect("/path/to/bar.out"); + directory_entry e(p); + TEST_CHECK(e.path() == p); + e.replace_filename(replace); + TEST_CHECK(e.path() == expect); + } +} + +TEST_CASE(test_replace_filename_ec_method) { + using namespace fs; + + { + directory_entry e; + path replace; + std::error_code ec; + static_assert(noexcept(e.replace_filename(replace, ec)) == false, + "operation cannot be noexcept"); + static_assert( + std::is_same::value, + "operation must return void"); + } + { + const path p("/path/to/foo.exe"); + const path replace("bar.out"); + const path expect("/path/to/bar.out"); + directory_entry e(p); + TEST_CHECK(e.path() == p); + std::error_code ec = GetTestEC(); + e.replace_filename(replace, ec); + TEST_CHECK(e.path() == expect); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + } + { + const path p = StaticEnv::EmptyFile; + const path expect = StaticEnv::NonEmptyFile; + const path replace = StaticEnv::NonEmptyFile.filename(); + TEST_REQUIRE(expect.parent_path() == p.parent_path()); + directory_entry e(p); + TEST_CHECK(e.path() == p); + std::error_code ec = GetTestEC(); + e.replace_filename(replace, ec); + TEST_CHECK(e.path() == expect); + TEST_CHECK(!ec); + } +} + +TEST_CASE(test_replace_filename_calls_refresh) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path file_two = env.create_file("dir/file_two", 101); + const path sym = env.create_symlink("dir/file", "sym"); + const path sym_two = env.create_symlink("dir/file_two", "sym_two"); + + { + directory_entry ent(file); + ent.replace_filename(file_two.filename()); + TEST_REQUIRE(ent.path() == file_two); + + // removing the file demonstrates that the values where cached previously. + LIBCPP_ONLY(remove(file_two)); + + TEST_CHECK(ent.file_size() == 101); + } + env.create_file("dir/file_two", 99); + { + directory_entry ent(sym); + ent.replace_filename(sym_two.filename()); + TEST_REQUIRE(ent.path() == sym_two); + + LIBCPP_ONLY(remove(file_two)); + LIBCPP_ONLY(remove(sym_two)); + + TEST_CHECK(ent.is_symlink()); + TEST_CHECK(ent.is_regular_file()); + TEST_CHECK(ent.file_size() == 99); + } +} + +TEST_CASE(test_replace_filename_propagates_error) { + using namespace fs; + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path file_two = env.create_file("dir/file_two", 99); + const path file_out_of_dir = env.create_file("file_three", 101); + const path sym_out_of_dir = env.create_symlink("dir/file", "sym"); + const path sym_out_of_dir_two = env.create_symlink("dir/file", "sym_two"); + const path sym_in_dir = env.create_symlink("file_two", "dir/sym_three"); + const path sym_in_dir_two = env.create_symlink("file_two", "dir/sym_four"); + + const perms old_perms = status(dir).permissions(); + + { + directory_entry ent(file); + permissions(dir, perms::none); + std::error_code ec = GetTestEC(); + ent.replace_filename(file_two.filename(), ec); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + } + permissions(dir, old_perms); + { + directory_entry ent(sym_in_dir); + permissions(dir, perms::none); + std::error_code ec = GetTestEC(); + ent.replace_filename(sym_in_dir_two.filename(), ec); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + } + permissions(dir, old_perms); + { + directory_entry ent(sym_out_of_dir); + permissions(dir, perms::none); + std::error_code ec = GetTestEC(); + ent.replace_filename(sym_out_of_dir_two.filename(), ec); + TEST_CHECK(!ec); + TEST_CHECK(ent.is_symlink()); + ec = GetTestEC(); + TEST_CHECK(!ent.exists(ec)); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp new file mode 100644 index 000000000..8048ad2b8 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp @@ -0,0 +1,238 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// uintmax_t file_size() const; +// uintmax_t file_size(error_code const&) const noexcept; + +#include "filesystem_include.hpp" +#include +#include + +#include "filesystem_test_helper.hpp" +#include "rapid-cxx-test.hpp" + +#include + +TEST_SUITE(directory_entry_obs_testsuite) + +TEST_CASE(signatures) { + using namespace fs; + { + const fs::directory_entry e; + std::error_code ec; + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, + ""); + static_assert(noexcept(e.file_size()) == false, ""); + static_assert(noexcept(e.file_size(ec)) == true, ""); + } +} + +TEST_CASE(basic) { + using namespace fs; + + scoped_test_env env; + const path file = env.create_file("file", 42); + const path dir = env.create_dir("dir"); + const path sym = env.create_symlink("file", "sym"); + + { + directory_entry ent(file); + uintmax_t expect = file_size(ent); + TEST_CHECK(expect == 42); + + // Remove the file to show that the results were already in the cache. + LIBCPP_ONLY(remove(file)); + + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == expect); + TEST_CHECK(!ec); + } + env.create_file("file", 99); + { + directory_entry ent(sym); + + uintmax_t expect = file_size(ent); + TEST_CHECK(expect == 99); + + LIBCPP_ONLY(remove(ent)); + + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == 99); + TEST_CHECK(!ec); + } +} + +TEST_CASE(not_regular_file) { + using namespace fs; + + scoped_test_env env; + struct { + const path p; + std::errc expected_err; + } TestCases[] = { + {env.create_dir("dir"), std::errc::is_a_directory}, + {env.create_fifo("fifo"), std::errc::not_supported}, + {env.create_symlink("dir", "sym"), std::errc::is_a_directory}}; + + for (auto const& TC : TestCases) { + const path& p = TC.p; + directory_entry ent(p); + TEST_CHECK(ent.path() == p); + std::error_code ec = GetTestEC(0); + + std::error_code other_ec = GetTestEC(1); + uintmax_t expect = file_size(p, other_ec); + + uintmax_t got = ent.file_size(ec); + TEST_CHECK(got == expect); + TEST_CHECK(got == uintmax_t(-1)); + TEST_CHECK(ec == other_ec); + TEST_CHECK(ErrorIs(ec, TC.expected_err)); + + ExceptionChecker Checker(p, TC.expected_err); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); + } +} + +TEST_CASE(error_reporting) { + using namespace fs; + + scoped_test_env env; + + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path file_out_of_dir = env.create_file("file2", 101); + const path sym_out_of_dir = env.create_symlink("dir/file", "sym"); + const path sym_in_dir = env.create_symlink("file2", "dir/sym2"); + + const perms old_perms = status(dir).permissions(); + + // test a file which doesn't exist + { + directory_entry ent; + + std::error_code ec = GetTestEC(); + ent.assign(StaticEnv::DNE, ec); + TEST_REQUIRE(ent.path() == StaticEnv::DNE); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ExceptionChecker Checker(StaticEnv::DNE, + std::errc::no_such_file_or_directory); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); + } + // test a dead symlink + { + directory_entry ent; + + std::error_code ec = GetTestEC(); + uintmax_t expect_bad = file_size(StaticEnv::BadSymlink, ec); + TEST_CHECK(expect_bad == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ec = GetTestEC(); + ent.assign(StaticEnv::BadSymlink, ec); + TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink); + TEST_CHECK(!ec); + + ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == expect_bad); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ExceptionChecker Checker(StaticEnv::BadSymlink, + std::errc::no_such_file_or_directory); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); + } + // test a file w/o appropriate permissions. + { + directory_entry ent; + uintmax_t expect_good = file_size(file); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + ent.assign(file, ec); + TEST_REQUIRE(ent.path() == file); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ExceptionChecker Checker(file, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); + + permissions(dir, old_perms); + ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == expect_good); + TEST_CHECK(!ec); + TEST_CHECK_NO_THROW(ent.file_size()); + } + permissions(dir, old_perms); + // test a symlink w/o appropriate permissions. + { + directory_entry ent; + uintmax_t expect_good = file_size(sym_in_dir); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + ent.assign(sym_in_dir, ec); + TEST_REQUIRE(ent.path() == sym_in_dir); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); + + permissions(dir, old_perms); + ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == expect_good); + TEST_CHECK(!ec); + TEST_CHECK_NO_THROW(ent.file_size()); + } + permissions(dir, old_perms); + // test a symlink to a file w/o appropriate permissions + { + directory_entry ent; + uintmax_t expect_good = file_size(sym_out_of_dir); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + ent.assign(sym_out_of_dir, ec); + TEST_REQUIRE(ent.path() == sym_out_of_dir); + TEST_CHECK(!ec); + + ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); + + permissions(dir, old_perms); + ec = GetTestEC(); + TEST_CHECK(ent.file_size(ec) == expect_good); + TEST_CHECK(!ec); + TEST_CHECK_NO_THROW(ent.file_size()); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp new file mode 100644 index 000000000..fbd860823 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp @@ -0,0 +1,258 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// file_status status() const; +// file_status status(error_code const&) const noexcept; + +#include "filesystem_include.hpp" +#include +#include + +#include "filesystem_test_helper.hpp" +#include "rapid-cxx-test.hpp" + +TEST_SUITE(directory_entry_obs_testsuite) + +TEST_CASE(file_dne) { + using namespace fs; + directory_entry p("dne"); +} + +TEST_CASE(signatures) { + using namespace fs; + const directory_entry e; + std::error_code ec; +#define TEST_FUNC(name) \ + static_assert(std::is_same::value, \ + "wrong return type"); \ + static_assert(noexcept(e.name()) == false, "should not be noexcept"); \ + static_assert(std::is_same::value, \ + "wrong return type"); \ + static_assert(noexcept(e.name(ec)) == true, "should be noexcept") + + TEST_FUNC(exists); + TEST_FUNC(is_block_file); + TEST_FUNC(is_character_file); + TEST_FUNC(is_directory); + TEST_FUNC(is_fifo); + TEST_FUNC(is_other); + TEST_FUNC(is_regular_file); + TEST_FUNC(is_socket); + TEST_FUNC(is_symlink); + +#undef TEST_FUNC +} + +TEST_CASE(test_without_ec) { + using namespace fs; + using fs::directory_entry; + using fs::file_status; + using fs::path; + + scoped_test_env env; + path f = env.create_file("foo", 42); + path d = env.create_dir("dir"); + path fifo = env.create_fifo("fifo"); + path hl = env.create_hardlink("foo", "hl"); + for (auto p : {hl, f, d, fifo}) { + directory_entry e(p); + file_status st = status(p); + file_status sym_st = symlink_status(p); + fs::remove(p); + TEST_REQUIRE(e.exists()); + TEST_REQUIRE(!exists(p)); + TEST_CHECK(e.exists() == exists(st)); + TEST_CHECK(e.is_block_file() == is_block_file(st)); + TEST_CHECK(e.is_character_file() == is_character_file(st)); + TEST_CHECK(e.is_directory() == is_directory(st)); + TEST_CHECK(e.is_fifo() == is_fifo(st)); + TEST_CHECK(e.is_other() == is_other(st)); + TEST_CHECK(e.is_regular_file() == is_regular_file(st)); + TEST_CHECK(e.is_socket() == is_socket(st)); + TEST_CHECK(e.is_symlink() == is_symlink(sym_st)); + } +} + +TEST_CASE(test_with_ec) { + using namespace fs; + using fs::directory_entry; + using fs::file_status; + using fs::path; + + scoped_test_env env; + path f = env.create_file("foo", 42); + path d = env.create_dir("dir"); + path fifo = env.create_fifo("fifo"); + path hl = env.create_hardlink("foo", "hl"); + for (auto p : {hl, f, d, fifo}) { + directory_entry e(p); + std::error_code status_ec = GetTestEC(); + std::error_code sym_status_ec = GetTestEC(1); + file_status st = status(p, status_ec); + file_status sym_st = symlink_status(p, sym_status_ec); + fs::remove(p); + std::error_code ec = GetTestEC(2); + auto CheckEC = [&](std::error_code const& other_ec) { + bool res = ec == other_ec; + ec = GetTestEC(2); + return res; + }; + + TEST_REQUIRE(e.exists(ec)); + TEST_CHECK(CheckEC(status_ec)); + TEST_REQUIRE(!exists(p)); + + TEST_CHECK(e.exists(ec) == exists(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_block_file(ec) == is_block_file(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_character_file(ec) == is_character_file(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_directory(ec) == is_directory(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_fifo(ec) == is_fifo(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_other(ec) == is_other(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_socket(ec) == is_socket(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st)); + TEST_CHECK(CheckEC(sym_status_ec)); + } +} + +TEST_CASE(test_with_ec_dne) { + using namespace fs; + using fs::directory_entry; + using fs::file_status; + using fs::path; + + for (auto p : {StaticEnv::DNE, StaticEnv::BadSymlink}) { + + directory_entry e(p); + std::error_code status_ec = GetTestEC(); + std::error_code sym_status_ec = GetTestEC(1); + file_status st = status(p, status_ec); + file_status sym_st = symlink_status(p, sym_status_ec); + std::error_code ec = GetTestEC(2); + auto CheckEC = [&](std::error_code const& other_ec) { + bool res = ec == other_ec; + ec = GetTestEC(2); + return res; + }; + + TEST_CHECK(e.exists(ec) == exists(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_block_file(ec) == is_block_file(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_character_file(ec) == is_character_file(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_directory(ec) == is_directory(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_fifo(ec) == is_fifo(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_other(ec) == is_other(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_socket(ec) == is_socket(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st)); + TEST_CHECK(CheckEC(sym_status_ec)); + } +} + +TEST_CASE(test_with_ec_cannot_resolve) { + using namespace fs; + using fs::directory_entry; + using fs::file_status; + using fs::path; + + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path file_out_of_dir = env.create_file("file2", 99); + const path sym = env.create_symlink("file2", "dir/sym"); + + perms old_perms = fs::status(dir).permissions(); + + for (auto p : {file, sym}) { + permissions(dir, old_perms); + directory_entry e(p); + + permissions(dir, perms::none); + std::error_code dummy_ec; + e.refresh(dummy_ec); + TEST_REQUIRE(dummy_ec); + + std::error_code status_ec = GetTestEC(); + std::error_code sym_status_ec = GetTestEC(1); + file_status st = status(p, status_ec); + file_status sym_st = symlink_status(p, sym_status_ec); + std::error_code ec = GetTestEC(2); + auto CheckEC = [&](std::error_code const& other_ec) { + bool res = ec == other_ec; + ec = GetTestEC(2); + return res; + }; + + TEST_CHECK(e.exists(ec) == exists(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_block_file(ec) == is_block_file(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_character_file(ec) == is_character_file(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_directory(ec) == is_directory(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_fifo(ec) == is_fifo(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_other(ec) == is_other(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_regular_file(ec) == is_regular_file(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_socket(ec) == is_socket(st)); + TEST_CHECK(CheckEC(status_ec)); + + TEST_CHECK(e.is_symlink(ec) == is_symlink(sym_st)); + TEST_CHECK(CheckEC(sym_status_ec)); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp new file mode 100644 index 000000000..fcb21c764 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp @@ -0,0 +1,237 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// uintmax_t hard_link_count() const; +// uintmax_t hard_link_count(error_code const&) const noexcept; + +#include "filesystem_include.hpp" +#include +#include + +#include "filesystem_test_helper.hpp" +#include "rapid-cxx-test.hpp" + +TEST_SUITE(directory_entry_obs_testsuite) + +TEST_CASE(signatures) { + using namespace fs; + { + const fs::directory_entry e; + std::error_code ec; + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, + ""); + static_assert(noexcept(e.hard_link_count()) == false, ""); + static_assert(noexcept(e.hard_link_count(ec)) == true, ""); + } +} + +TEST_CASE(basic) { + using namespace fs; + + scoped_test_env env; + const path file = env.create_file("file", 42); + const path dir = env.create_dir("dir"); + const path sym = env.create_symlink("file", "sym"); + + { + directory_entry ent(file); + uintmax_t expect = hard_link_count(ent); + + // Remove the file to show that the results were already in the cache. + LIBCPP_ONLY(remove(file)); + + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == expect); + TEST_CHECK(!ec); + } + { + directory_entry ent(dir); + uintmax_t expect = hard_link_count(ent); + + LIBCPP_ONLY(remove(dir)); + + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == expect); + TEST_CHECK(!ec); + } + env.create_file("file", 99); + env.create_hardlink("file", "hl"); + { + directory_entry ent(sym); + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == 2); + TEST_CHECK(!ec); + } +} + +TEST_CASE(not_regular_file) { + using namespace fs; + + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path dir2 = env.create_dir("dir/dir2"); + const path fifo = env.create_fifo("dir/fifo"); + const path sym_to_fifo = env.create_symlink("dir/fifo", "dir/sym"); + + const perms old_perms = status(dir).permissions(); + + for (auto p : {dir2, fifo, sym_to_fifo}) { + permissions(dir, old_perms); + std::error_code dummy_ec = GetTestEC(); + directory_entry ent(p, dummy_ec); + TEST_CHECK(!dummy_ec); + + uintmax_t expect = hard_link_count(p); + + LIBCPP_ONLY(permissions(dir, perms::none)); + + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == expect); + TEST_CHECK(!ec); + TEST_CHECK_NO_THROW(ent.hard_link_count()); + } +} + +TEST_CASE(error_reporting) { + using namespace fs; + + scoped_test_env env; + + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path file_out_of_dir = env.create_file("file2", 101); + const path sym_out_of_dir = env.create_symlink("dir/file", "sym"); + const path sym_in_dir = env.create_symlink("file2", "dir/sym2"); + + const perms old_perms = status(dir).permissions(); + + // test a file which doesn't exist + { + directory_entry ent; + + std::error_code ec = GetTestEC(); + ent.assign(StaticEnv::DNE, ec); + TEST_CHECK(ec); + TEST_REQUIRE(ent.path() == StaticEnv::DNE); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ExceptionChecker Checker(StaticEnv::DNE, + std::errc::no_such_file_or_directory); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count()); + } + // test a dead symlink + { + directory_entry ent; + + std::error_code ec = GetTestEC(); + uintmax_t expect_bad = hard_link_count(StaticEnv::BadSymlink, ec); + TEST_CHECK(expect_bad == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ec = GetTestEC(); + ent.assign(StaticEnv::BadSymlink, ec); + TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink); + TEST_CHECK(!ec); + + ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == expect_bad); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ExceptionChecker Checker(StaticEnv::BadSymlink, + std::errc::no_such_file_or_directory); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count()); + } + // test a file w/o appropriate permissions. + { + directory_entry ent; + uintmax_t expect_good = hard_link_count(file); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + ent.assign(file, ec); + TEST_REQUIRE(ent.path() == file); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ExceptionChecker Checker(file, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count()); + + permissions(dir, old_perms); + ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == expect_good); + TEST_CHECK(!ec); + TEST_CHECK_NO_THROW(ent.hard_link_count()); + } + permissions(dir, old_perms); + // test a symlink w/o appropriate permissions. + { + directory_entry ent; + uintmax_t expect_good = hard_link_count(sym_in_dir); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + ent.assign(sym_in_dir, ec); + TEST_REQUIRE(ent.path() == sym_in_dir); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count()); + + permissions(dir, old_perms); + ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == expect_good); + TEST_CHECK(!ec); + TEST_CHECK_NO_THROW(ent.hard_link_count()); + } + permissions(dir, old_perms); + // test a symlink to a file w/o appropriate permissions + { + directory_entry ent; + uintmax_t expect_good = hard_link_count(sym_out_of_dir); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + ent.assign(sym_out_of_dir, ec); + TEST_REQUIRE(ent.path() == sym_out_of_dir); + TEST_CHECK(!ec); + + ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1)); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count()); + + permissions(dir, old_perms); + ec = GetTestEC(); + TEST_CHECK(ent.hard_link_count(ec) == expect_good); + TEST_CHECK(!ec); + TEST_CHECK_NO_THROW(ent.hard_link_count()); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp new file mode 100644 index 000000000..c89e16709 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp @@ -0,0 +1,210 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// class directory_entry + +// file_time_type last_write_time() const; +// file_time_type last_write_time(error_code const&) const noexcept; + +#include "filesystem_include.hpp" +#include +#include + +#include "filesystem_test_helper.hpp" +#include "rapid-cxx-test.hpp" + +TEST_SUITE(directory_entry_obs_testsuite) + +TEST_CASE(signatures) { + using namespace fs; + { + const fs::directory_entry e; + std::error_code ec; + static_assert(std::is_same::value, + ""); + static_assert(std::is_same::value, + ""); + static_assert(noexcept(e.last_write_time()) == false, ""); + static_assert(noexcept(e.last_write_time(ec)) == true, ""); + } +} + +TEST_CASE(basic) { + using namespace fs; + + scoped_test_env env; + const path file = env.create_file("file", 42); + const path dir = env.create_dir("dir"); + const path sym = env.create_symlink("file", "sym"); + + { + directory_entry ent(file); + file_time_type expect = last_write_time(ent); + + // Remove the file to show that the results were already in the cache. + LIBCPP_ONLY(remove(file)); + + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == expect); + TEST_CHECK(!ec); + } + { + directory_entry ent(dir); + file_time_type expect = last_write_time(ent); + + LIBCPP_ONLY(remove(dir)); + + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == expect); + TEST_CHECK(!ec); + } + env.create_file("file", 99); + { + directory_entry ent(sym); + file_time_type expect = last_write_time(sym); + + std::error_code ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == expect); + TEST_CHECK(!ec); + } +} + +TEST_CASE(error_reporting) { + using namespace fs; + + scoped_test_env env; + + const path dir = env.create_dir("dir"); + const path file = env.create_file("dir/file", 42); + const path file_out_of_dir = env.create_file("file2", 101); + const path sym_out_of_dir = env.create_symlink("dir/file", "sym"); + const path sym_in_dir = env.create_symlink("file2", "dir/sym2"); + + const perms old_perms = status(dir).permissions(); + + // test a file which doesn't exist + { + directory_entry ent; + + std::error_code ec = GetTestEC(); + ent.assign(StaticEnv::DNE, ec); + TEST_REQUIRE(ent.path() == StaticEnv::DNE); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == file_time_type::min()); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ExceptionChecker Checker(StaticEnv::DNE, + std::errc::no_such_file_or_directory); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time()); + } + // test a dead symlink + { + directory_entry ent; + + std::error_code ec = GetTestEC(); + file_time_type expect_bad = last_write_time(StaticEnv::BadSymlink, ec); + TEST_CHECK(expect_bad == file_time_type::min()); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ec = GetTestEC(); + ent.assign(StaticEnv::BadSymlink, ec); + TEST_REQUIRE(ent.path() == StaticEnv::BadSymlink); + TEST_CHECK(!ec); + + ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == expect_bad); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); + + ExceptionChecker Checker(StaticEnv::BadSymlink, + std::errc::no_such_file_or_directory); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time()); + } + // test a file w/o appropriate permissions. + { + directory_entry ent; + file_time_type expect_good = last_write_time(file); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + ent.assign(file, ec); + TEST_REQUIRE(ent.path() == file); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == file_time_type::min()); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ExceptionChecker Checker(file, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time()); + + permissions(dir, old_perms); + ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == expect_good); + TEST_CHECK(!ec); + TEST_CHECK_NO_THROW(ent.last_write_time()); + } + permissions(dir, old_perms); + // test a symlink w/o appropriate permissions. + { + directory_entry ent; + file_time_type expect_good = last_write_time(sym_in_dir); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + ent.assign(sym_in_dir, ec); + TEST_REQUIRE(ent.path() == sym_in_dir); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == file_time_type::min()); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time()); + + permissions(dir, old_perms); + ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == expect_good); + TEST_CHECK(!ec); + TEST_CHECK_NO_THROW(ent.last_write_time()); + } + permissions(dir, old_perms); + // test a symlink to a file w/o appropriate permissions + { + directory_entry ent; + file_time_type expect_good = last_write_time(sym_out_of_dir); + permissions(dir, perms::none); + + std::error_code ec = GetTestEC(); + ent.assign(sym_out_of_dir, ec); + TEST_REQUIRE(ent.path() == sym_out_of_dir); + TEST_CHECK(!ec); + + ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == file_time_type::min()); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time()); + + permissions(dir, old_perms); + ec = GetTestEC(); + TEST_CHECK(ent.last_write_time(ec) == expect_good); + TEST_CHECK(!ec); + TEST_CHECK_NO_THROW(ent.last_write_time()); + } +} + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp index f234f0c1a..1f15850ce 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp @@ -21,31 +21,38 @@ #include #include "filesystem_test_helper.hpp" +#include "rapid-cxx-test.hpp" -int main() -{ +TEST_SUITE(directory_entry_status_testsuite) + +TEST_CASE(test_basic) { using namespace fs; { - const directory_entry e("foo"); + const fs::directory_entry e("foo"); std::error_code ec; - static_assert(std::is_same::value, ""); - static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, ""); + static_assert(std::is_same::value, ""); static_assert(noexcept(e.status()) == false, ""); static_assert(noexcept(e.status(ec)) == true, ""); } - auto TestFn = [](path const& p) { + path TestCases[] = {StaticEnv::File, StaticEnv::Dir, StaticEnv::SymlinkToFile, + StaticEnv::DNE}; + for (const auto& p : TestCases) { const directory_entry e(p); - std::error_code pec, eec; + std::error_code pec = GetTestEC(), eec = GetTestEC(1); file_status ps = fs::status(p, pec); file_status es = e.status(eec); - assert(ps.type() == es.type()); - assert(ps.permissions() == es.permissions()); - assert(pec == eec); - }; - { - TestFn(StaticEnv::File); - TestFn(StaticEnv::Dir); - TestFn(StaticEnv::SymlinkToFile); - TestFn(StaticEnv::DNE); + TEST_CHECK(ps.type() == es.type()); + TEST_CHECK(ps.permissions() == es.permissions()); + TEST_CHECK(pec == eec); + } + for (const auto& p : TestCases) { + const directory_entry e(p); + file_status ps = fs::status(p); + file_status es = e.status(); + TEST_CHECK(ps.type() == es.type()); + TEST_CHECK(ps.permissions() == es.permissions()); } } + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp index 2ed22df3b..ed6aca2c7 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp @@ -21,8 +21,11 @@ #include #include "filesystem_test_helper.hpp" +#include "rapid-cxx-test.hpp" -int main() { +TEST_SUITE(directory_entry_obs_suite) + +TEST_CASE(test_signature) { using namespace fs; { const directory_entry e("foo"); @@ -32,19 +35,24 @@ int main() { static_assert(noexcept(e.symlink_status()) == false, ""); static_assert(noexcept(e.symlink_status(ec)) == true, ""); } - auto TestFn = [](path const& p) { + path TestCases[] = {StaticEnv::File, StaticEnv::Dir, StaticEnv::SymlinkToFile, + StaticEnv::DNE}; + for (const auto& p : TestCases) { const directory_entry e(p); - std::error_code pec, eec; + std::error_code pec = GetTestEC(), eec = GetTestEC(1); file_status ps = fs::symlink_status(p, pec); file_status es = e.symlink_status(eec); - assert(ps.type() == es.type()); - assert(ps.permissions() == es.permissions()); - assert(pec == eec); - }; - { - TestFn(StaticEnv::File); - TestFn(StaticEnv::Dir); - TestFn(StaticEnv::SymlinkToFile); - TestFn(StaticEnv::DNE); + TEST_CHECK(ps.type() == es.type()); + TEST_CHECK(ps.permissions() == es.permissions()); + TEST_CHECK(pec == eec); + } + for (const auto& p : TestCases) { + const directory_entry e(p); + file_status ps = fs::symlink_status(p); + file_status es = e.symlink_status(); + TEST_CHECK(ps.type() == es.type()); + TEST_CHECK(ps.permissions() == es.permissions()); } } + +TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp index 1f7b87ae8..e2b2513ec 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp @@ -62,17 +62,22 @@ TEST_CASE(symlink_test_case) TEST_CASE(file_size_error_cases) { - const path testCases[] = { - StaticEnv::Dir, - StaticEnv::SymlinkToDir, - StaticEnv::BadSymlink, - StaticEnv::DNE - }; + struct { + path p; + std::errc expected_err; + } TestCases[] = { + {StaticEnv::Dir, std::errc::is_a_directory}, + {StaticEnv::SymlinkToDir, std::errc::is_a_directory}, + {StaticEnv::BadSymlink, std::errc::no_such_file_or_directory}, + {StaticEnv::DNE, std::errc::no_such_file_or_directory}}; const uintmax_t expect = static_cast(-1); - for (auto& TC : testCases) { - std::error_code ec; - TEST_CHECK(file_size(TC, ec) == expect); - TEST_CHECK(ec); + for (auto& TC : TestCases) { + std::error_code ec = GetTestEC(); + TEST_CHECK(file_size(TC.p, ec) == expect); + TEST_CHECK(ErrorIs(ec, TC.expected_err)); + + ExceptionChecker Checker(TC.p, TC.expected_err); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, file_size(TC.p)); } } diff --git a/test/support/filesystem_test_helper.hpp b/test/support/filesystem_test_helper.hpp index 5a8a32a40..e3f46a16a 100644 --- a/test/support/filesystem_test_helper.hpp +++ b/test/support/filesystem_test_helper.hpp @@ -8,6 +8,9 @@ #include #include #include +#include + +#include "rapid-cxx-test.hpp" // static test helpers @@ -381,8 +384,39 @@ bool checkCollectionsEqualBackwards( // We often need to test that the error_code was cleared if no error occurs // this function returns an error_code which is set to an error that will // never be returned by the filesystem functions. -inline std::error_code GetTestEC() { - return std::make_error_code(std::errc::address_family_not_supported); +inline std::error_code GetTestEC(unsigned Idx = 0) { + using std::errc; + auto GetErrc = [&]() { + switch (Idx) { + case 0: + return errc::address_family_not_supported; + case 1: + return errc::address_not_available; + case 2: + return errc::address_in_use; + case 3: + return errc::argument_list_too_long; + default: + assert(false && "Idx out of range"); + std::abort(); + } + }; + return std::make_error_code(GetErrc()); +} + +inline bool ErrorIsImp(const std::error_code& ec, + std::vector const& errors) { + for (auto errc : errors) { + if (ec == std::make_error_code(errc)) + return true; + } + return false; +} + +template +inline bool ErrorIs(const std::error_code& ec, std::errc First, ErrcT... Rest) { + std::vector errors = {First, Rest...}; + return ErrorIsImp(ec, errors); } // Provide our own Sleep routine since std::this_thread::sleep_for is not @@ -403,4 +437,26 @@ inline bool PathEq(fs::path const& LHS, fs::path const& RHS) { return LHS.native() == RHS.native(); } +struct ExceptionChecker { + std::vector expected_err_list; + fs::path expected_path1; + fs::path expected_path2; + + template + explicit ExceptionChecker(fs::path p, std::errc first_err, ErrcT... rest_err) + : expected_err_list({first_err, rest_err...}), expected_path1(p) {} + + template + explicit ExceptionChecker(fs::path p1, fs::path p2, std::errc first_err, + ErrcT... rest_err) + : expected_err_list({first_err, rest_err...}), expected_path1(p1), + expected_path2(p2) {} + + void operator()(fs::filesystem_error const& Err) const { + TEST_CHECK(ErrorIsImp(Err.code(), expected_err_list)); + TEST_CHECK(Err.path1() == expected_path1); + TEST_CHECK(Err.path2() == expected_path2); + } +}; + #endif /* FILESYSTEM_TEST_HELPER_HPP */ diff --git a/test/support/rapid-cxx-test.hpp b/test/support/rapid-cxx-test.hpp index a25bda531..eb24ac259 100644 --- a/test/support/rapid-cxx-test.hpp +++ b/test/support/rapid-cxx-test.hpp @@ -221,6 +221,24 @@ namespace Name \ } while (false) # +#define TEST_CHECK_THROW_RESULT(Except, Checker, ...) \ + do { \ + TEST_SET_CHECKPOINT(); \ + ::rapid_cxx_test::test_outcome m_f(::rapid_cxx_test::failure_type::none, \ + __FILE__, TEST_FUNC_NAME(), __LINE__, \ + "TEST_CHECK_THROW_RESULT(" #Except \ + "," #Checker "," #__VA_ARGS__ ")", \ + ""); \ + try { \ + (static_cast(__VA_ARGS__)); \ + m_f.type = ::rapid_cxx_test::failure_type::check; \ + } catch (Except const& Caught) { \ + Checker(Caught); \ + } \ + ::rapid_cxx_test::get_reporter().report(m_f); \ + } while (false) +# + #else // TEST_HAS_NO_EXCEPTIONS # define TEST_CHECK_NO_THROW(...) \ @@ -236,6 +254,7 @@ namespace Name \ # #define TEST_CHECK_THROW(Except, ...) ((void)0) +#define TEST_CHECK_THROW_RESULT(Except, Checker, ...) ((void)0) #endif // TEST_HAS_NO_EXCEPTIONS diff --git a/www/cxx1z_status.html b/www/cxx1z_status.html index ab86d1a13..3d826acf3 100644 --- a/www/cxx1z_status.html +++ b/www/cxx1z_status.html @@ -148,7 +148,7 @@ P0156R2LWGVariadic Lock guard(rev 5)KonaComplete5.0 P0270R3CWGRemoving C dependencies from signal handler wordingKona P0298R3CWGA byte type definitionKonaComplete5.0 - P0317R1LWGDirectory Entry Caching for FilesystemKona + P0317R1LWGDirectory Entry Caching for FilesystemKonaComplete7.0 P0430R2LWGFile system library on non-POSIX-like operating systemsKonaComplete7.0 P0433R2LWGToward a resolution of US7 and US14: Integrating template deduction for class templates into the standard libraryKonaIn progress7.0 P0452R1LWGUnifying <numeric> Parallel AlgorithmsKona -- GitLab From f8bfc79ac50f04b15c4aa3305255071736b02dcb Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 20 Jul 2018 01:25:06 +0000 Subject: [PATCH 039/495] cleanup test assertion inside library git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337517 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/operations.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index 449b60975..126aec501 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -25,11 +25,6 @@ #include /* values for fchmodat */ #include -#ifdef NDEBUG -#undef NDEBUG -#endif -#include - _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM filesystem_error::~filesystem_error() {} @@ -298,7 +293,6 @@ file_status create_file_status(std::error_code& m_ec, path const& p, struct ::stat& path_stat, std::error_code* ec) { if (ec) *ec = m_ec; - // assert(m_ec.value() != ENOTDIR); if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { return file_status(file_type::not_found); } else if (m_ec) { -- GitLab From 0f8ee948c3c35735909da59b2d9be0995835c0b9 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 20 Jul 2018 01:44:33 +0000 Subject: [PATCH 040/495] Use _LIBCPP_UNREACHABLE to convince GCC that non-void functions actually always return git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337519 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/experimental/filesystem | 8 ++++++++ src/experimental/filesystem/filesystem_common.h | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/experimental/filesystem b/include/experimental/filesystem index be73bf135..6481aa680 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -232,6 +232,7 @@ #include #include +#include #include #include #include @@ -2250,6 +2251,7 @@ private: __ec->clear(); return __data_.__type_; } + _LIBCPP_UNREACHABLE(); } _LIBCPP_INLINE_VISIBILITY @@ -2270,6 +2272,7 @@ private: return __data_.__type_; } } + _LIBCPP_UNREACHABLE(); } _LIBCPP_INLINE_VISIBILITY @@ -2284,6 +2287,7 @@ private: case _RefreshSymlink: return file_status(__get_ft(__ec), __data_.__non_sym_perms_); } + _LIBCPP_UNREACHABLE(); } _LIBCPP_INLINE_VISIBILITY @@ -2299,6 +2303,7 @@ private: case _RefreshSymlinkUnresolved: return file_status(__get_sym_ft(__ec), __data_.__sym_perms_); } + _LIBCPP_UNREACHABLE(); } @@ -2324,6 +2329,7 @@ private: return __data_.__size_; } } + _LIBCPP_UNREACHABLE(); } _LIBCPP_INLINE_VISIBILITY @@ -2342,6 +2348,7 @@ private: return __data_.__nlink_; } } + _LIBCPP_UNREACHABLE(); } _LIBCPP_INLINE_VISIBILITY @@ -2364,6 +2371,7 @@ private: return __data_.__write_time_; } } + _LIBCPP_UNREACHABLE(); } private: _Path __p_; diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index ab7ecbd01..0dd6e9ee4 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -228,8 +228,8 @@ public: } // namespace time_util -using TimeSpec = struct timespec; -using StatT = struct stat; +using TimeSpec = struct ::timespec; +using StatT = struct ::stat; using FSTime = time_util::fs_time_util; -- GitLab From 77c9cf44e39b62df1c0e7cafd00390623ec37c4e Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 20 Jul 2018 01:51:48 +0000 Subject: [PATCH 041/495] Fix two test failures in First, didn't correctly guard against min/max macros. This adds the proper push/pop macro guards. Second, an internal time helper had been renamed but the test for it hadn't been updated. This patch updates those tests. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337520 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/experimental/filesystem | 5 +++++ test/libcxx/experimental/filesystem/convert_file_time.sh.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/experimental/filesystem b/include/experimental/filesystem index 6481aa680..2d2c11765 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -251,6 +251,9 @@ #pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + #define __cpp_lib_experimental_filesystem 201406 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM @@ -2647,4 +2650,6 @@ recursive_directory_iterator end(const recursive_directory_iterator&) _NOEXCEPT _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM +_LIBCPP_POP_MACROS + #endif // _LIBCPP_EXPERIMENTAL_FILESYSTEM diff --git a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp b/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp index e418851d9..cc1696cea 100644 --- a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp +++ b/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp @@ -28,7 +28,7 @@ using namespace std::chrono; namespace fs = std::experimental::filesystem; using fs::file_time_type; -using fs::detail::fs_time_util; +using fs::detail::time_util::fs_time_util; enum TestKind { TK_64Bit, TK_32Bit, TK_FloatingPoint }; -- GitLab From 7b1b6ca284ca4dfc1f67e4bf88ccb5a5c551e152 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 20 Jul 2018 08:36:45 +0000 Subject: [PATCH 042/495] adjust incorrect comment git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337532 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/operations.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index 126aec501..28851028a 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -1426,7 +1426,8 @@ error_code directory_entry::__do_refresh() noexcept { __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; return error_code{}; } - // Otherwise, we resolved the link as not existing. That's OK. + // Otherwise, we either resolved the link, potentially as not existing. + // That's OK. __data_.__cache_type_ = directory_entry::_RefreshSymlink; } -- GitLab From 4d34ec08506b4df31ca65a806d10beefa1776f82 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Fri, 20 Jul 2018 22:45:24 +0000 Subject: [PATCH 043/495] [CMake] Install C++ ABI headers into the right location This is a follow-up to r335809 and r337118. While libc++ headers are now installed into the right location in both standard as well as multiarch runtimes layout, turned out C++ ABI headers are still installed into the old location in the latter case. This change addresses that. Differential Revision: https://reviews.llvm.org/D49584 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337630 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/Modules/HandleLibCXXABI.cmake | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/cmake/Modules/HandleLibCXXABI.cmake b/cmake/Modules/HandleLibCXXABI.cmake index 797b504eb..0eb70a739 100644 --- a/cmake/Modules/HandleLibCXXABI.cmake +++ b/cmake/Modules/HandleLibCXXABI.cmake @@ -32,14 +32,6 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs) set(LIBCXX_CXX_ABI_LIBRARY ${abilib}) set(LIBCXX_ABILIB_FILES ${abifiles}) - # The place in the build tree where we store out-of-source headers. - file(MAKE_DIRECTORY "${LIBCXX_BUILD_HEADERS_ROOT}") - file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/c++/v1") - foreach(_d ${abidirs}) - file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}/${_d}") - file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include/c++/v1/${_d}") - endforeach() - foreach(fpath ${LIBCXX_ABILIB_FILES}) set(found FALSE) foreach(incpath ${LIBCXX_CXX_ABI_INCLUDE_PATHS}) @@ -56,7 +48,7 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs) COMMENT "Copying C++ ABI header ${fpath}...") list(APPEND abilib_headers "${dst}") - set(dst "${CMAKE_BINARY_DIR}/include/c++/v1/${dstdir}/${fpath}") + set(dst "${LIBCXX_HEADER_DIR}/include/c++/v1/${dstdir}/${fpath}") add_custom_command(OUTPUT ${dst} DEPENDS ${src} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} @@ -65,7 +57,7 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs) if (LIBCXX_INSTALL_HEADERS) install(FILES "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}" - DESTINATION ${LIBCXX_INSTALL_PATH}include/c++/v1/${dstdir} + DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1/${dstdir} COMPONENT cxx-headers PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) -- GitLab From 70c866bfc13f6d1518bddbac53cbeb4842d080cd Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sun, 22 Jul 2018 02:00:53 +0000 Subject: [PATCH 044/495] Implement a better copy_file. This patch improves both the performance, and the safety of the copy_file implementation. The performance improvements are achieved by using sendfile on Linux and copyfile on OS X when available. The TOCTOU hardening is achieved by opening the source and destination files and then using fstat to check their attributes to see if we can copy them. Unfortunately for the destination file, there is no way to open it without accidentally creating it, so we first have to use stat to determine if it exists, and if we should copy to it. Then, once we're sure we should try to copy, we open the dest file and ensure it names the same entity we previously stat'ed. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337649 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/fstream | 216 ++++++----- src/experimental/filesystem/operations.cpp | 358 ++++++++++++++---- .../fs.op.copy_file/copy_file.pass.cpp | 285 +++++++------- .../fs.op.copy_file/copy_file_large.pass.cpp | 99 +++++ test/support/filesystem_test_helper.hpp | 28 +- test/support/rapid-cxx-test.hpp | 4 +- 6 files changed, 666 insertions(+), 324 deletions(-) create mode 100644 test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp diff --git a/include/fstream b/include/fstream index 2ef4cf318..8b9aefaac 100644 --- a/include/fstream +++ b/include/fstream @@ -170,6 +170,7 @@ typedef basic_fstream wfstream; #include #include <__locale> #include +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -217,10 +218,17 @@ public: #endif _LIBCPP_INLINE_VISIBILITY basic_filebuf* open(const string& __s, ios_base::openmode __mode); + + _LIBCPP_INLINE_VISIBILITY + basic_filebuf* __open(int __fd, ios_base::openmode __mode); #endif basic_filebuf* close(); -protected: + _LIBCPP_INLINE_VISIBILITY + inline static const char* + __make_mdstring(ios_base::openmode __mode) _NOEXCEPT; + + protected: // 27.9.1.5 Overridden virtual functions: virtual int_type underflow(); virtual int_type pbackfail(int_type __c = traits_type::eof()); @@ -234,25 +242,25 @@ protected: virtual void imbue(const locale& __loc); private: - char* __extbuf_; - const char* __extbufnext_; - const char* __extbufend_; - char __extbuf_min_[8]; - size_t __ebs_; - char_type* __intbuf_; - size_t __ibs_; - FILE* __file_; - const codecvt* __cv_; - state_type __st_; - state_type __st_last_; - ios_base::openmode __om_; - ios_base::openmode __cm_; - bool __owns_eb_; - bool __owns_ib_; - bool __always_noconv_; - - bool __read_mode(); - void __write_mode(); + char* __extbuf_; + const char* __extbufnext_; + const char* __extbufend_; + char __extbuf_min_[8]; + size_t __ebs_; + char_type* __intbuf_; + size_t __ibs_; + FILE* __file_; + const codecvt* __cv_; + state_type __st_; + state_type __st_last_; + ios_base::openmode __om_; + ios_base::openmode __cm_; + bool __owns_eb_; + bool __owns_ib_; + bool __always_noconv_; + + bool __read_mode(); + void __write_mode(); }; template @@ -473,6 +481,46 @@ basic_filebuf<_CharT, _Traits>::is_open() const return __file_ != 0; } +template +const char* basic_filebuf<_CharT, _Traits>::__make_mdstring( + ios_base::openmode __mode) _NOEXCEPT { + switch (__mode & ~ios_base::ate) { + case ios_base::out: + case ios_base::out | ios_base::trunc: + return "w"; + case ios_base::out | ios_base::app: + case ios_base::app: + return "a"; + case ios_base::in: + return "r"; + case ios_base::in | ios_base::out: + return "r+"; + case ios_base::in | ios_base::out | ios_base::trunc: + return "w+"; + case ios_base::in | ios_base::out | ios_base::app: + case ios_base::in | ios_base::app: + return "a+"; + case ios_base::out | ios_base::binary: + case ios_base::out | ios_base::trunc | ios_base::binary: + return "wb"; + case ios_base::out | ios_base::app | ios_base::binary: + case ios_base::app | ios_base::binary: + return "ab"; + case ios_base::in | ios_base::binary: + return "rb"; + case ios_base::in | ios_base::out | ios_base::binary: + return "r+b"; + case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary: + return "w+b"; + case ios_base::in | ios_base::out | ios_base::app | ios_base::binary: + case ios_base::in | ios_base::app | ios_base::binary: + return "a+b"; + default: + return nullptr; + } + _LIBCPP_UNREACHABLE(); +} + #ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE template basic_filebuf<_CharT, _Traits>* @@ -481,79 +529,49 @@ basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) basic_filebuf<_CharT, _Traits>* __rt = 0; if (__file_ == 0) { + if (const char* __mdstr = __make_mdstring(__mode)) { __rt = this; - const char* __mdstr; - switch (__mode & ~ios_base::ate) - { - case ios_base::out: - case ios_base::out | ios_base::trunc: - __mdstr = "w"; - break; - case ios_base::out | ios_base::app: - case ios_base::app: - __mdstr = "a"; - break; - case ios_base::in: - __mdstr = "r"; - break; - case ios_base::in | ios_base::out: - __mdstr = "r+"; - break; - case ios_base::in | ios_base::out | ios_base::trunc: - __mdstr = "w+"; - break; - case ios_base::in | ios_base::out | ios_base::app: - case ios_base::in | ios_base::app: - __mdstr = "a+"; - break; - case ios_base::out | ios_base::binary: - case ios_base::out | ios_base::trunc | ios_base::binary: - __mdstr = "wb"; - break; - case ios_base::out | ios_base::app | ios_base::binary: - case ios_base::app | ios_base::binary: - __mdstr = "ab"; - break; - case ios_base::in | ios_base::binary: - __mdstr = "rb"; - break; - case ios_base::in | ios_base::out | ios_base::binary: - __mdstr = "r+b"; - break; - case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary: - __mdstr = "w+b"; - break; - case ios_base::in | ios_base::out | ios_base::app | ios_base::binary: - case ios_base::in | ios_base::app | ios_base::binary: - __mdstr = "a+b"; - break; - default: - __rt = 0; - break; - } - if (__rt) - { - __file_ = fopen(__s, __mdstr); - if (__file_) - { - __om_ = __mode; - if (__mode & ios_base::ate) - { - if (fseek(__file_, 0, SEEK_END)) - { - fclose(__file_); - __file_ = 0; - __rt = 0; - } - } + __file_ = fopen(__s, __mdstr); + if (__file_) { + __om_ = __mode; + if (__mode & ios_base::ate) { + if (fseek(__file_, 0, SEEK_END)) { + fclose(__file_); + __file_ = 0; + __rt = 0; } - else - __rt = 0; - } + } + } else + __rt = 0; + } } return __rt; } +template +_LIBCPP_INLINE_VISIBILITY basic_filebuf<_CharT, _Traits>* +basic_filebuf<_CharT, _Traits>::__open(int __fd, ios_base::openmode __mode) { + basic_filebuf<_CharT, _Traits>* __rt = 0; + if (__file_ == 0) { + if (const char* __mdstr = __make_mdstring(__mode)) { + __rt = this; + __file_ = fdopen(__fd, __mdstr); + if (__file_) { + __om_ = __mode; + if (__mode & ios_base::ate) { + if (fseek(__file_, 0, SEEK_END)) { + fclose(__file_); + __file_ = 0; + __rt = 0; + } + } + } else + __rt = 0; + } + } + return __rt; +} + #ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR // This is basically the same as the char* overload except that it uses _wfopen // and long mode strings. @@ -1131,6 +1149,9 @@ public: void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in); #endif void open(const string& __s, ios_base::openmode __mode = ios_base::in); + + _LIBCPP_INLINE_VISIBILITY + void __open(int __fd, ios_base::openmode __mode); #endif _LIBCPP_INLINE_VISIBILITY void close(); @@ -1265,6 +1286,15 @@ basic_ifstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mo else this->setstate(ios_base::failbit); } + +template +void basic_ifstream<_CharT, _Traits>::__open(int __fd, + ios_base::openmode __mode) { + if (__sb_.__open(__fd, __mode | ios_base::in)) + this->clear(); + else + this->setstate(ios_base::failbit); +} #endif template @@ -1319,6 +1349,9 @@ public: void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::out); #endif void open(const string& __s, ios_base::openmode __mode = ios_base::out); + + _LIBCPP_INLINE_VISIBILITY + void __open(int __fd, ios_base::openmode __mode); #endif _LIBCPP_INLINE_VISIBILITY void close(); @@ -1453,6 +1486,15 @@ basic_ofstream<_CharT, _Traits>::open(const string& __s, ios_base::openmode __mo else this->setstate(ios_base::failbit); } + +template +void basic_ofstream<_CharT, _Traits>::__open(int __fd, + ios_base::openmode __mode) { + if (__sb_.__open(__fd, __mode | ios_base::out)) + this->clear(); + else + this->setstate(ios_base::failbit); +} #endif template diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index 28851028a..be876ad77 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -23,7 +23,17 @@ #include #include #include /* values for fchmodat */ -#include + +#if defined(__linux__) +# include +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) +# include +# define _LIBCPP_USE_SENDFILE +# endif +#elif defined(__APPLE__) || __has_include() +#include +# define _LIBCPP_USE_COPYFILE +#endif _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM @@ -281,6 +291,63 @@ namespace detail { namespace { using value_type = path::value_type; using string_type = path::string_type; +struct FileDescriptor { + const path& name; + int fd = -1; + StatT m_stat; + file_status m_status; + + template + static FileDescriptor create(const path* p, error_code& ec, Args... args) { + ec.clear(); + int fd; + if ((fd = ::open(p->c_str(), args...)) == -1) { + ec = capture_errno(); + return FileDescriptor{p}; + } + return FileDescriptor(p, fd); + } + + template + static FileDescriptor create_with_status(const path* p, error_code& ec, + Args... args) { + FileDescriptor fd = create(p, ec, args...); + if (!ec) + fd.refresh_status(ec); + + return fd; + } + + file_status get_status() const { return m_status; } + StatT const& get_stat() const { return m_stat; } + + bool status_known() const { return _VSTD_FS::status_known(m_status); } + + file_status refresh_status(std::error_code& ec); + + void close() noexcept { + if (fd != -1) + ::close(fd); + fd = -1; + } + + FileDescriptor(FileDescriptor&& other) + : name(other.name), fd(other.fd), m_stat(other.m_stat), + m_status(other.m_status) { + other.fd = -1; + other.m_status = file_status{}; + } + + ~FileDescriptor() { close(); } + + FileDescriptor() = default; + FileDescriptor(FileDescriptor const&) = delete; + FileDescriptor& operator=(FileDescriptor const&) = delete; + +private: + explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {} +}; + perms posix_get_perms(const struct ::stat& st) noexcept { return static_cast(st.st_mode) & perms::mask; } @@ -290,7 +357,8 @@ perms posix_get_perms(const struct ::stat& st) noexcept { } file_status create_file_status(std::error_code& m_ec, path const& p, - struct ::stat& path_stat, std::error_code* ec) { + const struct ::stat& path_stat, + std::error_code* ec) { if (ec) *ec = m_ec; if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { @@ -350,37 +418,39 @@ file_status posix_lstat(path const& p, std::error_code* ec) { return posix_lstat(p, path_stat, ec); } -bool stat_equivalent(struct ::stat& st1, struct ::stat& st2) { - return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); +bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, + std::error_code& ec) { + if (::ftruncate(fd.fd, to_size) == -1) { + ec = capture_errno(); + return false; + } + ec.clear(); + return true; } -// DETAIL::MISC - +bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) { + if (::fchmod(fd.fd, st.st_mode) == -1) { + ec = capture_errno(); + return false; + } + ec.clear(); + return true; +} -bool copy_file_impl(const path& from, const path& to, perms from_perms, - std::error_code *ec) -{ - std::ifstream in(from.c_str(), std::ios::binary); - std::ofstream out(to.c_str(), std::ios::binary); - - if (in.good() && out.good()) { - using InIt = std::istreambuf_iterator; - using OutIt = std::ostreambuf_iterator; - InIt bin(in); - InIt ein; - OutIt bout(out); - std::copy(bin, ein, bout); - } - if (out.fail() || in.fail()) { - set_or_throw(make_error_code(errc::operation_not_permitted), - ec, "copy_file", from, to); - return false; - } - __permissions(to, from_perms, perm_options::replace, ec); - // TODO what if permissions fails? - return true; +bool stat_equivalent(const StatT& st1, const StatT& st2) { + return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); } +file_status FileDescriptor::refresh_status(std::error_code& ec) { + // FD must be open and good. + m_status = file_status{}; + m_stat = StatT{}; + std::error_code m_ec; + if (::fstat(fd, &m_stat) == -1) + m_ec = capture_errno(); + m_status = create_file_status(m_ec, name, m_stat, &ec); + return m_status; +} }} // end namespace detail using detail::set_or_throw; @@ -503,64 +573,195 @@ void __copy(const path& from, const path& to, copy_options options, } } +namespace detail { +namespace { + + +#ifdef _LIBCPP_USE_SENDFILE +bool copy_file_impl_sendfile(FileDescriptor& read_fd, FileDescriptor& write_fd, + error_code& ec) { + + size_t count = read_fd.get_stat().st_size; + do { + ssize_t res; + if ((res = ::sendfile(write_fd.fd, read_fd.fd, nullptr, count)) == -1) { + ec = capture_errno(); + return false; + } + count -= res; + } while (count > 0); + + ec.clear(); + + return true; +} +#elif defined(_LIBCPP_USE_COPYFILE) +bool copy_file_impl_copyfile(FileDescriptor& read_fd, FileDescriptor& write_fd, + error_code& ec) { + struct CopyFileState { + copyfile_state_t state; + CopyFileState() { state = copyfile_state_alloc(); } + ~CopyFileState() { copyfile_state_free(state); } + + private: + CopyFileState(CopyFileState const&) = delete; + CopyFileState& operator=(CopyFileState const&) = delete; + }; + + CopyFileState cfs; + if (fcopyfile(read_fd.fd, write_fd.fd, cfs.state, COPYFILE_DATA) < 0) { + ec = capture_errno(); + return false; + } + + ec.clear(); + return true; +} +#endif + +// Note: This function isn't guarded by ifdef's even though it may be unused +// in order to assure it still compiles. +__attribute__((unused)) bool copy_file_impl_default(FileDescriptor& read_fd, + FileDescriptor& write_fd, + error_code& ec) { + std::ifstream in; + in.__open(read_fd.fd, std::ios::binary); + if (!in.is_open()) { + // This assumes that __open didn't reset the error code. + ec = capture_errno(); + return false; + } + std::ofstream out; + out.__open(write_fd.fd, std::ios::binary); + if (!out.is_open()) { + ec = capture_errno(); + return false; + } + + if (in.good() && out.good()) { + using InIt = std::istreambuf_iterator; + using OutIt = std::ostreambuf_iterator; + InIt bin(in); + InIt ein; + OutIt bout(out); + std::copy(bin, ein, bout); + } + if (out.fail() || in.fail()) { + ec = make_error_code(errc::io_error); + return false; + } + + ec.clear(); + return true; +} + +bool copy_file_impl(FileDescriptor& from, FileDescriptor& to, error_code& ec) { +#if defined(_LIBCPP_USE_SENDFILE) + return copy_file_impl_sendfile(from, to, ec); +#elif defined(_LIBCPP_USE_COPYFILE) + return copy_file_impl_copyfile(from, to, ec); +#else + return copy_file_impl_default(from, to, ec); +#endif +} + +} // namespace +} // namespace detail bool __copy_file(const path& from, const path& to, copy_options options, std::error_code *ec) { - using StatT = struct ::stat; - if (ec) - ec->clear(); + using detail::FileDescriptor; + using detail::StatT; - std::error_code m_ec; - StatT from_stat; - auto from_st = detail::posix_stat(from, from_stat, &m_ec); - if (not is_regular_file(from_st)) { - if (not m_ec) - m_ec = make_error_code(errc::not_supported); - set_or_throw(m_ec, ec, "copy_file", from, to); - return false; - } + if (ec) + ec->clear(); - StatT to_stat; - auto to_st = detail::posix_stat(to, to_stat, &m_ec); - if (!status_known(to_st)) { - set_or_throw(m_ec, ec, "copy_file", from, to); - return false; - } + auto Error = [&](const error_code& error_ec) { + set_or_throw(error_ec, ec, "copy_file", from, to); + return false; + }; - const bool to_exists = exists(to_st); - if (to_exists && !is_regular_file(to_st)) { - set_or_throw(make_error_code(errc::not_supported), ec, "copy_file", from, to); + std::error_code m_ec; + FileDescriptor from_fd = + FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK); + if (m_ec) + return Error(m_ec); + + auto from_st = from_fd.get_status(); + StatT const& from_stat = from_fd.get_stat(); + if (!is_regular_file(from_st)) { + if (not m_ec) + m_ec = make_error_code(errc::not_supported); + return Error(m_ec); + } + + const bool skip_existing = bool(copy_options::skip_existing & options); + const bool update_existing = bool(copy_options::update_existing & options); + const bool overwrite_existing = + bool(copy_options::overwrite_existing & options); + + StatT to_stat_path; + file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec); + if (!status_known(to_st)) + return Error(m_ec); + + const bool to_exists = exists(to_st); + if (to_exists && !is_regular_file(to_st)) + return Error(make_error_code(errc::not_supported)); + + if (to_exists && detail::stat_equivalent(from_stat, to_stat_path)) + return Error(make_error_code(errc::file_exists)); + + if (to_exists && skip_existing) + return false; + + auto ShouldCopy = [&]() { + if (to_exists && update_existing) { + auto from_time = detail::extract_mtime(from_stat); + auto to_time = detail::extract_mtime(to_stat_path); + if (from_time.tv_sec < to_time.tv_sec) return false; - } - if (to_exists && detail::stat_equivalent(from_stat, to_stat)) { - set_or_throw(make_error_code(errc::file_exists), ec, "copy_file", from, - to); - return false; - } - if (to_exists && bool(copy_options::skip_existing & options)) { + if (from_time.tv_sec == to_time.tv_sec && + from_time.tv_nsec <= to_time.tv_nsec) return false; + return true; } - else if (to_exists && bool(copy_options::update_existing & options)) { - auto from_time = __last_write_time(from, ec); - if (ec && *ec) { return false; } - auto to_time = __last_write_time(to, ec); - if (ec && *ec) { return false; } - if (from_time <= to_time) { - return false; - } - return detail::copy_file_impl(from, to, from_st.permissions(), ec); - } - else if (!to_exists || bool(copy_options::overwrite_existing & options)) { - return detail::copy_file_impl(from, to, from_st.permissions(), ec); - } - else { - set_or_throw(make_error_code(errc::file_exists), ec, "copy_file", from, - to); - return false; - } + if (!to_exists || overwrite_existing) + return true; + return Error(make_error_code(errc::file_exists)); + }; + if (!ShouldCopy()) + return false; + + // Don't truncate right away. We may not be opening the file we originally + // looked at; we'll check this later. + int to_open_flags = O_WRONLY | O_CREAT; + FileDescriptor to_fd = FileDescriptor::create_with_status( + &to, m_ec, to_open_flags, from_stat.st_mode); + if (m_ec) + return Error(m_ec); + + if (to_exists) { + // Check that the file we initially stat'ed is equivalent to the one + // we opened. + if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat())) + return Error(make_error_code(errc::bad_file_descriptor)); + + // Set the permissions and truncate the file we opened. + if (!detail::posix_fchmod(to_fd, from_stat, m_ec)) + return Error(m_ec); + if (!detail::posix_ftruncate(to_fd, 0, m_ec)) + return Error(m_ec); + } + + if (!copy_file_impl(from_fd, to_fd, m_ec)) { + // FIXME: Remove the dest file if we failed, and it didn't exist previously. + return Error(m_ec); + } + + return true; - _LIBCPP_UNREACHABLE(); } void __copy_symlink(const path& existing_symlink, const path& new_symlink, @@ -759,9 +960,9 @@ bool __fs_is_empty(const path& p, std::error_code *ec) _LIBCPP_UNREACHABLE(); } -static file_time_type __extract_last_write_time(path const& p, +static file_time_type __extract_last_write_time(const path& p, const struct ::stat& st, - error_code *ec) { + error_code* ec) { using detail::FSTime; auto ts = detail::extract_mtime(st); if (!FSTime::is_representable(ts)) { @@ -1426,7 +1627,7 @@ error_code directory_entry::__do_refresh() noexcept { __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; return error_code{}; } - // Otherwise, we either resolved the link, potentially as not existing. + // Otherwise, we resolved the link, potentially as not existing. // That's OK. __data_.__cache_type_ = directory_entry::_RefreshSymlink; } @@ -1479,7 +1680,6 @@ error_code directory_entry::__do_refresh() noexcept { __data_.__cache_type_ = directory_entry::_RefreshSymlinkUnresolved; return error_code{}; } - // Otherwise, we resolved the link as not existing. That's OK. __data_.__cache_type_ = directory_entry::_RefreshSymlink; } diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp index 33b3ba9b5..3c2543ab9 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp @@ -26,167 +26,164 @@ #include "rapid-cxx-test.hpp" #include "filesystem_test_helper.hpp" +#include + using namespace fs; using CO = fs::copy_options; TEST_SUITE(filesystem_copy_file_test_suite) -TEST_CASE(test_signatures) -{ - const path p; ((void)p); - const copy_options opts{}; ((void)opts); - std::error_code ec; ((void)ec); - ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p)), bool); - ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts)), bool); - ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, ec)), bool); - ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts, ec)), bool); - ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p)); - ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts)); - ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, ec)); - ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts, ec)); +TEST_CASE(test_signatures) { + const path p; + ((void)p); + const copy_options opts{}; + ((void)opts); + std::error_code ec; + ((void)ec); + ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p)), bool); + ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts)), bool); + ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, ec)), bool); + ASSERT_SAME_TYPE(decltype(fs::copy_file(p, p, opts, ec)), bool); + ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p)); + ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts)); + ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, ec)); + ASSERT_NOT_NOEXCEPT(fs::copy_file(p, p, opts, ec)); } -TEST_CASE(test_error_reporting) -{ - auto checkThrow = [](path const& f, path const& t, const std::error_code& ec) - { -#ifndef TEST_HAS_NO_EXCEPTIONS - try { - fs::copy_file(f, t); - return false; - } catch (filesystem_error const& err) { - return err.path1() == f - && err.path2() == t - && err.code() == ec; - } -#else - ((void)f); ((void)t); ((void)ec); - return true; -#endif - }; - - scoped_test_env env; - const path file = env.create_file("file1", 42); - const path file2 = env.create_file("file2", 55); - const path non_regular_file = env.create_fifo("non_reg"); - const path dne = env.make_env_path("dne"); - { // exists(to) && equivalent(to, from) - std::error_code ec; - TEST_CHECK(fs::copy_file(file, file, copy_options::overwrite_existing, - ec) == false); - TEST_REQUIRE(ec); - TEST_CHECK(ec == std::make_error_code(std::errc::file_exists)); - TEST_CHECK(checkThrow(file, file, ec)); - } - { // exists(to) && !(skip_existing | overwrite_existing | update_existing) - std::error_code ec; - TEST_CHECK(fs::copy_file(file, file2, ec) == false); - TEST_REQUIRE(ec); - TEST_CHECK(ec == std::make_error_code(std::errc::file_exists)); - TEST_CHECK(checkThrow(file, file2, ec)); - } +TEST_CASE(test_error_reporting) { + + scoped_test_env env; + const path file = env.create_file("file1", 42); + const path file2 = env.create_file("file2", 55); + const path non_regular_file = env.create_fifo("non_reg"); + const path dne = env.make_env_path("dne"); + + { // exists(to) && equivalent(to, from) + std::error_code ec; + TEST_CHECK(fs::copy_file(file, file, copy_options::overwrite_existing, + ec) == false); + TEST_CHECK(ErrorIs(ec, std::errc::file_exists)); + ExceptionChecker Checker(file, file, std::errc::file_exists); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing)); + + } + { // exists(to) && !(skip_existing | overwrite_existing | update_existing) + std::error_code ec; + TEST_CHECK(fs::copy_file(file, file2, ec) == false); + TEST_CHECK(ErrorIs(ec, std::errc::file_exists)); + ExceptionChecker Checker(file, file, std::errc::file_exists); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing)); + + } +} + +TEST_CASE(non_regular_file_test) { + scoped_test_env env; + const path fifo = env.create_fifo("fifo"); + const path dest = env.make_env_path("dest"); + const path file = env.create_file("file", 42); + + { + std::error_code ec = GetTestEC(); + TEST_REQUIRE(fs::copy_file(fifo, dest, ec) == false); + TEST_CHECK(ErrorIs(ec, std::errc::not_supported)); + TEST_CHECK(!exists(dest)); + } + { + std::error_code ec = GetTestEC(); + TEST_REQUIRE(fs::copy_file(file, fifo, copy_options::overwrite_existing, + ec) == false); + TEST_CHECK(ErrorIs(ec, std::errc::not_supported)); + TEST_CHECK(is_fifo(fifo)); + } + } -TEST_CASE(copy_file) -{ - scoped_test_env env; - const path file = env.create_file("file1", 42); - - { // !exists(to) - const path dest = env.make_env_path("dest1"); - std::error_code ec; - TEST_REQUIRE(fs::copy_file(file, dest, ec) == true); - TEST_CHECK(!ec); - TEST_CHECK(file_size(dest) == 42); - } - { // exists(to) && overwrite_existing - const path dest = env.create_file("dest2", 55); - std::error_code ec; - TEST_REQUIRE(fs::copy_file(file, dest, - copy_options::overwrite_existing, ec) == true); - TEST_CHECK(!ec); - TEST_CHECK(file_size(dest) == 42); - } - { // exists(to) && update_existing - using Sec = std::chrono::seconds; - const path older = env.create_file("older_file", 1); - - SleepFor(Sec(2)); - const path from = env.create_file("update_from", 55); - - SleepFor(Sec(2)); - const path newer = env.create_file("newer_file", 2); - - std::error_code ec; - TEST_REQUIRE(fs::copy_file(from, older, copy_options::update_existing, ec) == true); - TEST_CHECK(!ec); - TEST_CHECK(file_size(older) == 55); - - TEST_REQUIRE(fs::copy_file(from, newer, copy_options::update_existing, ec) == false); - TEST_CHECK(!ec); - TEST_CHECK(file_size(newer) == 2); - } - { // skip_existing - const path file2 = env.create_file("file2", 55); - std::error_code ec; - TEST_REQUIRE(fs::copy_file(file, file2, copy_options::skip_existing, ec) == false); - TEST_CHECK(!ec); - TEST_CHECK(file_size(file2) == 55); - } +TEST_CASE(test_attributes_get_copied) { + scoped_test_env env; + const path file = env.create_file("file1", 42); + const path dest = env.make_env_path("file2"); + auto st = status(file); + perms new_perms = perms::owner_read; + permissions(file, new_perms); + std::error_code ec = GetTestEC(); + TEST_REQUIRE(fs::copy_file(file, dest, ec) == true); + TEST_CHECK(!ec); + auto new_st = status(dest); + TEST_CHECK(new_st.permissions() == new_perms); } -TEST_CASE(test_attributes_get_copied) -{ - scoped_test_env env; - const path file = env.create_file("file1", 42); - const path dest = env.make_env_path("file2"); - auto st = status(file); - perms new_perms = perms::owner_read; - permissions(file, new_perms); - std::error_code ec; +TEST_CASE(copy_dir_test) { + scoped_test_env env; + const path file = env.create_file("file1", 42); + const path dest = env.create_dir("dir1"); + std::error_code ec = GetTestEC(); + TEST_CHECK(fs::copy_file(file, dest, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); + ec = GetTestEC(); + TEST_CHECK(fs::copy_file(dest, file, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(ec != GetTestEC()); +} + +TEST_CASE(copy_file) { + scoped_test_env env; + const path file = env.create_file("file1", 42); + + { // !exists(to) + const path dest = env.make_env_path("dest1"); + std::error_code ec = GetTestEC(); + TEST_REQUIRE(fs::copy_file(file, dest, ec) == true); TEST_CHECK(!ec); - auto new_st = status(dest); - TEST_CHECK(new_st.permissions() == new_perms); -} + TEST_CHECK(file_size(dest) == 42); + } + { // exists(to) && overwrite_existing + const path dest = env.create_file("dest2", 55); + permissions(dest, perms::all); + permissions(file, + perms::group_write | perms::owner_write | perms::others_write, + perm_options::remove); -TEST_CASE(copy_dir_test) -{ - scoped_test_env env; - const path file = env.create_file("file1", 42); - const path dest = env.create_dir("dir1"); std::error_code ec = GetTestEC(); - TEST_CHECK(fs::copy_file(file, dest, ec) == false); - TEST_CHECK(ec); - TEST_CHECK(ec != GetTestEC()); - ec = GetTestEC(); - TEST_CHECK(fs::copy_file(dest, file, ec) == false); - TEST_CHECK(ec); - TEST_CHECK(ec != GetTestEC()); -} + TEST_REQUIRE(fs::copy_file(file, dest, copy_options::overwrite_existing, + ec) == true); + TEST_CHECK(!ec); + TEST_CHECK(file_size(dest) == 42); + TEST_CHECK(status(dest).permissions() == status(file).permissions()); + } + { // exists(to) && update_existing + using Sec = std::chrono::seconds; + const path older = env.create_file("older_file", 1); + + SleepFor(Sec(2)); + const path from = env.create_file("update_from", 55); + + SleepFor(Sec(2)); + const path newer = env.create_file("newer_file", 2); -TEST_CASE(non_regular_file_test) -{ - scoped_test_env env; - const path fifo = env.create_fifo("fifo"); - const path dest = env.make_env_path("dest"); - const path file = env.create_file("file", 42); - { - std::error_code ec = GetTestEC(); - TEST_REQUIRE(fs::copy_file(fifo, dest, ec) == false); - TEST_CHECK(ec); - TEST_CHECK(ec != GetTestEC()); - TEST_CHECK(!exists(dest)); - } - { - std::error_code ec = GetTestEC(); - TEST_REQUIRE(fs::copy_file(file, fifo, copy_options::overwrite_existing, ec) == false); - TEST_CHECK(ec); - TEST_CHECK(ec != GetTestEC()); - TEST_CHECK(ec == std::make_error_code(std::errc::not_supported)); - TEST_CHECK(is_fifo(fifo)); - } + std::error_code ec = GetTestEC(); + TEST_REQUIRE( + fs::copy_file(from, older, copy_options::update_existing, ec) == true); + TEST_CHECK(!ec); + TEST_CHECK(file_size(older) == 55); + + TEST_REQUIRE( + fs::copy_file(from, newer, copy_options::update_existing, ec) == false); + TEST_CHECK(!ec); + TEST_CHECK(file_size(newer) == 2); + } + { // skip_existing + const path file2 = env.create_file("file2", 55); + std::error_code ec = GetTestEC(); + TEST_REQUIRE(fs::copy_file(file, file2, copy_options::skip_existing, ec) == + false); + TEST_CHECK(!ec); + TEST_CHECK(file_size(file2) == 55); + } } + TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp new file mode 100644 index 000000000..46b5f2a67 --- /dev/null +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 +// REQUIRES: long_tests + +// + +// bool copy_file(const path& from, const path& to); +// bool copy_file(const path& from, const path& to, error_code& ec) noexcept; +// bool copy_file(const path& from, const path& to, copy_options options); +// bool copy_file(const path& from, const path& to, copy_options options, +// error_code& ec) noexcept; + +#include "filesystem_include.hpp" +#include +#include +#include + +#include "test_macros.h" +#include "rapid-cxx-test.hpp" +#include "filesystem_test_helper.hpp" + +using namespace fs; + +TEST_SUITE(filesystem_copy_file_test_suite) + +static std::string random_hex_chars(uintmax_t size) { + std::string data; + data.reserve(size); + for (uintmax_t I = 0; I < size; ++I) + data.push_back(random_utils::random_hex_char()); + return data; +} + +// This test is intended to test 'sendfile's 2gb limit for a single call, and +// to ensure that libc++ correctly copies files larger than that limit. +// However it requires allocating ~5GB of filesystem space. This might not +// be acceptable on all systems. +TEST_CASE(large_file) { + using namespace fs; + constexpr uintmax_t sendfile_size_limit = 2147479552ull; + constexpr uintmax_t additional_size = 1024; + constexpr uintmax_t test_file_size = sendfile_size_limit + additional_size; + static_assert(test_file_size > sendfile_size_limit, ""); + + scoped_test_env env; + + // Check that we have more than sufficient room to create the files needed + // to perform the test. + if (space(env.test_root).available < 3 * test_file_size) { + TEST_UNSUPPORTED(); + } + + // Use python to create a file right at the size limit. + const path file = env.create_file("source", sendfile_size_limit); + // Create some random data that looks different than the data before the + // size limit. + const std::string additional_data = random_hex_chars(additional_size); + // Append this known data to the end of the source file. + { + std::ofstream outf(file.native(), std::ios_base::app); + TEST_REQUIRE(outf.good()); + outf << additional_data; + TEST_REQUIRE(outf); + } + TEST_REQUIRE(file_size(file) == test_file_size); + const path dest = env.make_env_path("dest"); + + std::error_code ec = GetTestEC(); + TEST_CHECK(copy_file(file, dest, ec)); + TEST_CHECK(!ec); + + TEST_REQUIRE(is_regular_file(dest)); + TEST_CHECK(file_size(dest) == test_file_size); + + // Read the data from the end of the destination file, and ensure it matches + // the data at the end of the source file. + std::string out_data; + out_data.reserve(additional_size); + { + std::ifstream dest_file(dest.native()); + TEST_REQUIRE(dest_file); + dest_file.seekg(sendfile_size_limit); + TEST_REQUIRE(dest_file); + dest_file >> out_data; + TEST_CHECK(dest_file.eof()); + } + TEST_CHECK(out_data.size() == additional_data.size()); + TEST_CHECK(out_data == additional_data); +} + +TEST_SUITE_END() diff --git a/test/support/filesystem_test_helper.hpp b/test/support/filesystem_test_helper.hpp index e3f46a16a..de06868c0 100644 --- a/test/support/filesystem_test_helper.hpp +++ b/test/support/filesystem_test_helper.hpp @@ -105,6 +105,20 @@ static const fs::path RecDirFollowSymlinksIterationList[] = { #error LIBCXX_FILESYSTEM_DYNAMIC_TEST_HELPER must be defined #endif +namespace random_utils { +inline char to_hex(int ch) { + return ch < 10 ? static_cast('0' + ch) + : static_cast('a' + (ch - 10)); +} + +inline char random_hex_char() { + static std::mt19937 rd{std::random_device{}()}; + static std::uniform_int_distribution mrand{0, 15}; + return to_hex(mrand(rd)); +} + +} // namespace random_utils + struct scoped_test_env { scoped_test_env() : test_root(random_env_path()) @@ -179,21 +193,11 @@ struct scoped_test_env fs::path const test_root; private: - static char to_hex(int ch) { - return ch < 10 ? static_cast('0' + ch) - : static_cast('a' + (ch - 10)); - } - - static char random_hex_char() { - static std::mt19937 rd { std::random_device{}() }; - static std::uniform_int_distribution mrand{0, 15}; - return to_hex( mrand(rd) ); - } - static std::string unique_path_suffix() { std::string model = "test.%%%%%%"; for (auto & ch : model) { - if (ch == '%') ch = random_hex_char(); + if (ch == '%') + ch = random_utils::random_hex_char(); } return model; } diff --git a/test/support/rapid-cxx-test.hpp b/test/support/rapid-cxx-test.hpp index eb24ac259..bf027407a 100644 --- a/test/support/rapid-cxx-test.hpp +++ b/test/support/rapid-cxx-test.hpp @@ -826,8 +826,8 @@ namespace rapid_cxx_test get_reporter().test_case_end(); } auto exit_code = get_reporter().failure_count() ? EXIT_FAILURE : EXIT_SUCCESS; - if (exit_code == EXIT_FAILURE) - get_reporter().print_summary(m_ts.name()); + if (exit_code == EXIT_FAILURE || get_reporter().unsupported_count()) + get_reporter().print_summary(m_ts.name()); return exit_code; } -- GitLab From 1061b65e6e59c1894e22fad012607eeaee8b6d69 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sun, 22 Jul 2018 20:50:16 +0000 Subject: [PATCH 045/495] fix test failures with older clang versions git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337658 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../default_const.pass.cpp | 32 +++++++++++++++++++ .../directory_entry.obs/file_size.pass.cpp | 2 +- .../file_type_obs.pass.cpp | 2 +- .../hard_link_count.pass.cpp | 2 +- .../last_write_time.pass.cpp | 2 +- 5 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default_const.pass.cpp diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default_const.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default_const.pass.cpp new file mode 100644 index 000000000..a94134c15 --- /dev/null +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default_const.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 +// XFAIL: apple-clang-7, clang-3.7, clang-3.8 + +// + +// class directory_entry + +// directory_entry() noexcept = default; + +#include "filesystem_include.hpp" +#include +#include + +int main() { + using namespace fs; + // Default + { + static_assert(std::is_nothrow_default_constructible::value, + "directory_entry must have a nothrow default constructor"); + const directory_entry e; + assert(e.path() == path()); + } +} diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp index 8048ad2b8..d5050edc7 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp @@ -30,7 +30,7 @@ TEST_SUITE(directory_entry_obs_testsuite) TEST_CASE(signatures) { using namespace fs; { - const fs::directory_entry e; + const fs::directory_entry e = {}; std::error_code ec; static_assert(std::is_same::value, ""); static_assert(std::is_same::value, diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp index fbd860823..a028de4b1 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp @@ -32,7 +32,7 @@ TEST_CASE(file_dne) { TEST_CASE(signatures) { using namespace fs; - const directory_entry e; + const directory_entry e = {}; std::error_code ec; #define TEST_FUNC(name) \ static_assert(std::is_same::value, \ diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp index fcb21c764..0ec801bb4 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp @@ -28,7 +28,7 @@ TEST_SUITE(directory_entry_obs_testsuite) TEST_CASE(signatures) { using namespace fs; { - const fs::directory_entry e; + const directory_entry e = {}; std::error_code ec; static_assert(std::is_same::value, ""); static_assert(std::is_same::value, diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp index c89e16709..250dc6f5a 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp @@ -28,7 +28,7 @@ TEST_SUITE(directory_entry_obs_testsuite) TEST_CASE(signatures) { using namespace fs; { - const fs::directory_entry e; + const fs::directory_entry e = {}; std::error_code ec; static_assert(std::is_same::value, ""); -- GitLab From fb03277e63674d182a41c31f5f71a88b8d89e0a2 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sun, 22 Jul 2018 21:15:15 +0000 Subject: [PATCH 046/495] Harden copy_file even more. This patch removes the O_CREAT open flag when we first attempt to open the destination file but we expect it to already exist. This theoretically avoids the possibility that it was removed between when we first stat'ed it, and when we attempt to open it. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337659 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/operations.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index be876ad77..cc744fb9b 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -716,7 +716,7 @@ bool __copy_file(const path& from, const path& to, copy_options options, if (to_exists && skip_existing) return false; - auto ShouldCopy = [&]() { + bool ShouldCopy = [&]() { if (to_exists && update_existing) { auto from_time = detail::extract_mtime(from_stat); auto to_time = detail::extract_mtime(to_stat_path); @@ -730,13 +730,15 @@ bool __copy_file(const path& from, const path& to, copy_options options, if (!to_exists || overwrite_existing) return true; return Error(make_error_code(errc::file_exists)); - }; - if (!ShouldCopy()) + }(); + if (!ShouldCopy) return false; // Don't truncate right away. We may not be opening the file we originally // looked at; we'll check this later. - int to_open_flags = O_WRONLY | O_CREAT; + int to_open_flags = O_WRONLY; + if (!to_exists) + to_open_flags |= O_CREAT; FileDescriptor to_fd = FileDescriptor::create_with_status( &to, m_ec, to_open_flags, from_stat.st_mode); if (m_ec) @@ -745,6 +747,7 @@ bool __copy_file(const path& from, const path& to, copy_options options, if (to_exists) { // Check that the file we initially stat'ed is equivalent to the one // we opened. + // FIXME: report this better. if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat())) return Error(make_error_code(errc::bad_file_descriptor)); @@ -761,7 +764,6 @@ bool __copy_file(const path& from, const path& to, copy_options options, } return true; - } void __copy_symlink(const path& existing_symlink, const path& new_symlink, -- GitLab From e14f03815bb3485bb5ea795adb2c895853b3d1b8 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sun, 22 Jul 2018 21:56:40 +0000 Subject: [PATCH 047/495] Workaround bug in GCC trunk. For some reason GCC ToT is failing to deduce the auto type for a static data member from its initializer in some cases. Though I'm sure the bug will be short lived, there is a trivial workaround for it. So we might as well get the bot passing again. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337661 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/filesystem_common.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index 0dd6e9ee4..187428309 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -94,18 +94,18 @@ using namespace chrono; template ::value> struct fs_time_util_base { - static constexpr auto max_seconds = + static constexpr seconds::rep max_seconds = duration_cast(FileTimeT::duration::max()).count(); - static constexpr auto max_nsec = + static constexpr nanoseconds::rep max_nsec = duration_cast(FileTimeT::duration::max() - seconds(max_seconds)) .count(); - static constexpr auto min_seconds = + static constexpr seconds::rep min_seconds = duration_cast(FileTimeT::duration::min()).count(); - static constexpr auto min_nsec_timespec = + static constexpr nanoseconds::rep min_nsec_timespec = duration_cast( (FileTimeT::duration::min() - seconds(min_seconds)) + seconds(1)) .count(); -- GitLab From 0ddb77a467e90256a57d06af8bf1900ec8890eaa Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 23 Jul 2018 02:00:52 +0000 Subject: [PATCH 048/495] Implement filesystem_error::what() and improve reporting. This patch implements the `what()` for filesystem errors. The message includes the 'what_arg', any paths that were specified, and the error code message. Additionally this patch refactors how errors are created, making it easier to report them correctly. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337664 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/experimental/filesystem | 61 +- .../filesystem/directory_iterator.cpp | 130 ++-- .../filesystem/filesystem_common.h | 150 ++++- src/experimental/filesystem/operations.cpp | 587 +++++++++--------- .../last_write_time.sh.cpp | 3 +- .../directory_entry.mods/refresh.pass.cpp | 6 +- .../directory_entry.obs/file_size.pass.cpp | 16 +- .../hard_link_count.pass.cpp | 15 +- .../last_write_time.pass.cpp | 15 +- .../rec.dir.itr.members/increment.pass.cpp | 19 +- .../fs.op.copy_file/copy_file.pass.cpp | 4 +- .../fs.op.file_size/file_size.pass.cpp | 5 +- test/support/filesystem_test_helper.hpp | 77 ++- test/support/format_string.hpp | 68 ++ www/cxx2a_status.html | 4 +- 15 files changed, 716 insertions(+), 444 deletions(-) create mode 100644 test/support/format_string.hpp diff --git a/include/experimental/filesystem b/include/experimental/filesystem index 2d2c11765..2ed3eecff 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -1265,40 +1265,51 @@ public: _LIBCPP_INLINE_VISIBILITY filesystem_error(const string& __what, error_code __ec) : system_error(__ec, __what), - __paths_(make_shared<_Storage>(path(), path())) - {} + __storage_(make_shared<_Storage>(path(), path())) { + __create_what(0); + } _LIBCPP_INLINE_VISIBILITY filesystem_error(const string& __what, const path& __p1, error_code __ec) : system_error(__ec, __what), - __paths_(make_shared<_Storage>(__p1, path())) - {} + __storage_(make_shared<_Storage>(__p1, path())) { + __create_what(1); + } _LIBCPP_INLINE_VISIBILITY filesystem_error(const string& __what, const path& __p1, const path& __p2, error_code __ec) : system_error(__ec, __what), - __paths_(make_shared<_Storage>(__p1, __p2)) - {} + __storage_(make_shared<_Storage>(__p1, __p2)) { + __create_what(2); + } _LIBCPP_INLINE_VISIBILITY - const path& path1() const _NOEXCEPT { - return __paths_->first; - } + const path& path1() const _NOEXCEPT { return __storage_->__p1_; } _LIBCPP_INLINE_VISIBILITY - const path& path2() const _NOEXCEPT { - return __paths_->second; - } + const path& path2() const _NOEXCEPT { return __storage_->__p2_; } ~filesystem_error() override; // key function - // TODO(ericwf): Create a custom error message. - //const char* what() const _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY + const char* what() const _NOEXCEPT override { + return __storage_->__what_.c_str(); + } -private: - typedef pair _Storage; - shared_ptr<_Storage> __paths_; + _LIBCPP_FUNC_VIS + void __create_what(int __num_paths); + + private: + struct _Storage { + _LIBCPP_INLINE_VISIBILITY + _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {} + + path __p1_; + path __p2_; + string __what_; + }; + shared_ptr<_Storage> __storage_; }; template @@ -1315,7 +1326,6 @@ void __throw_filesystem_error(_Args&&...) } #endif - // operational functions _LIBCPP_FUNC_VIS @@ -2226,12 +2236,13 @@ private: return; } if (__ec && (!__allow_dne || !__is_dne_error(__ec))) - __throw_filesystem_error(__msg, __p_, _Path{}, __ec); + __throw_filesystem_error(__msg, __p_, __ec); } _LIBCPP_INLINE_VISIBILITY void __refresh(error_code* __ec = nullptr) { - __handle_error("refresh", __ec, __do_refresh(), /*allow_dne*/ true); + __handle_error("in directory_entry::refresh", __ec, __do_refresh(), + /*allow_dne*/ true); } _LIBCPP_INLINE_VISIBILITY @@ -2322,11 +2333,11 @@ private: case _RefreshNonSymlink: { error_code __m_ec; file_status __st(__get_ft(&__m_ec)); - __handle_error("directory_entry::file_size", __ec, __m_ec); + __handle_error("in directory_entry::file_size", __ec, __m_ec); if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) { errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory : errc::not_supported; - __handle_error("directory_entry::file_size", __ec, + __handle_error("in directory_entry::file_size", __ec, make_error_code(__err_kind)); } return __data_.__size_; @@ -2347,7 +2358,7 @@ private: case _RefreshNonSymlink: { error_code __m_ec; (void)__get_ft(&__m_ec); - __handle_error("directory_entry::hard_link_count", __ec, __m_ec); + __handle_error("in directory_entry::hard_link_count", __ec, __m_ec); return __data_.__nlink_; } } @@ -2366,10 +2377,10 @@ private: case _RefreshNonSymlink: { error_code __m_ec; file_status __st(__get_ft(&__m_ec)); - __handle_error("directory_entry::last_write_time", __ec, __m_ec); + __handle_error("in directory_entry::last_write_time", __ec, __m_ec); if (_VSTD_FS::exists(__st) && __data_.__write_time_ == file_time_type::min()) - __handle_error("directory_entry::last_write_time", __ec, + __handle_error("in directory_entry::last_write_time", __ec, make_error_code(errc::value_too_large)); return __data_.__write_time_; } diff --git a/src/experimental/filesystem/directory_iterator.cpp b/src/experimental/filesystem/directory_iterator.cpp index b0b31450e..60f234cb1 100644 --- a/src/experimental/filesystem/directory_iterator.cpp +++ b/src/experimental/filesystem/directory_iterator.cpp @@ -88,7 +88,7 @@ static file_time_type get_write_time(const WIN32_FIND_DATA& data) { } // namespace } // namespace detail -using detail::set_or_throw; +using detail::ErrorHandler; #if defined(_LIBCPP_WIN32API) class __dir_stream { @@ -231,27 +231,30 @@ public: directory_iterator::directory_iterator(const path& p, error_code *ec, directory_options opts) { - std::error_code m_ec; - __imp_ = make_shared<__dir_stream>(p, opts, m_ec); - if (ec) *ec = m_ec; - if (!__imp_->good()) { - __imp_.reset(); - if (m_ec) - set_or_throw(m_ec, ec, - "directory_iterator::directory_iterator(...)", p); - } + ErrorHandler err("directory_iterator::directory_iterator(...)", ec, &p); + + std::error_code m_ec; + __imp_ = make_shared<__dir_stream>(p, opts, m_ec); + if (ec) + *ec = m_ec; + if (!__imp_->good()) { + __imp_.reset(); + if (m_ec) + err.report(m_ec); + } } directory_iterator& directory_iterator::__increment(error_code *ec) { _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator"); + ErrorHandler err("directory_iterator::operator++()", ec); + std::error_code m_ec; if (!__imp_->advance(m_ec)) { - __imp_.reset(); - if (m_ec) - set_or_throw(m_ec, ec, "directory_iterator::operator++()"); - } else { - if (ec) ec->clear(); + path root = std::move(__imp_->__root_); + __imp_.reset(); + if (m_ec) + err.report(m_ec, "at root \"%s\"", root); } return *this; @@ -273,15 +276,18 @@ recursive_directory_iterator::recursive_directory_iterator(const path& p, directory_options opt, error_code *ec) : __imp_(nullptr), __rec_(true) { - if (ec) ec->clear(); - std::error_code m_ec; - __dir_stream new_s(p, opt, m_ec); - if (m_ec) set_or_throw(m_ec, ec, "recursive_directory_iterator", p); - if (m_ec || !new_s.good()) return; - - __imp_ = _VSTD::make_shared<__shared_imp>(); - __imp_->__options_ = opt; - __imp_->__stack_.push(_VSTD::move(new_s)); + ErrorHandler err("recursive_directory_iterator", ec, &p); + + std::error_code m_ec; + __dir_stream new_s(p, opt, m_ec); + if (m_ec) + err.report(m_ec); + if (m_ec || !new_s.good()) + return; + + __imp_ = _VSTD::make_shared<__shared_imp>(); + __imp_->__options_ = opt; + __imp_->__stack_.push(_VSTD::move(new_s)); } void recursive_directory_iterator::__pop(error_code* ec) @@ -321,42 +327,50 @@ recursive_directory_iterator::__increment(error_code *ec) } void recursive_directory_iterator::__advance(error_code* ec) { - // REQUIRES: ec must be cleared before calling this function. - const directory_iterator end_it; - auto& stack = __imp_->__stack_; - std::error_code m_ec; - while (stack.size() > 0) { - if (stack.top().advance(m_ec)) - return; - if (m_ec) break; - stack.pop(); - } - __imp_.reset(); - if (m_ec) - set_or_throw(m_ec, ec, "recursive_directory_iterator::operator++()"); -} + ErrorHandler err("recursive_directory_iterator::operator++()", ec); -bool recursive_directory_iterator::__try_recursion(error_code *ec) { - bool rec_sym = - bool(options() & directory_options::follow_directory_symlink); - - auto& curr_it = __imp_->__stack_.top(); + const directory_iterator end_it; + auto& stack = __imp_->__stack_; + std::error_code m_ec; + while (stack.size() > 0) { + if (stack.top().advance(m_ec)) + return; + if (m_ec) + break; + stack.pop(); + } - bool skip_rec = false; - std::error_code m_ec; - if (!rec_sym) { - file_status st = curr_it.__entry_.symlink_status(m_ec); - if (m_ec && status_known(st)) - m_ec.clear(); - if (m_ec || is_symlink(st) || !is_directory(st)) - skip_rec = true; + if (m_ec) { + path root = std::move(stack.top().__root_); + __imp_.reset(); + err.report(m_ec, "at root \"%s\"", root); } else { - file_status st = curr_it.__entry_.status(m_ec); - if (m_ec && status_known(st)) - m_ec.clear(); - if (m_ec || !is_directory(st)) - skip_rec = true; + __imp_.reset(); } +} + +bool recursive_directory_iterator::__try_recursion(error_code *ec) { + ErrorHandler err("recursive_directory_iterator::operator++()", ec); + + bool rec_sym = bool(options() & directory_options::follow_directory_symlink); + + auto& curr_it = __imp_->__stack_.top(); + + bool skip_rec = false; + std::error_code m_ec; + if (!rec_sym) { + file_status st = curr_it.__entry_.symlink_status(m_ec); + if (m_ec && status_known(st)) + m_ec.clear(); + if (m_ec || is_symlink(st) || !is_directory(st)) + skip_rec = true; + } else { + file_status st = curr_it.__entry_.status(m_ec); + if (m_ec && status_known(st)) + m_ec.clear(); + if (m_ec || !is_directory(st)) + skip_rec = true; + } if (!skip_rec) { __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec); @@ -371,9 +385,9 @@ bool recursive_directory_iterator::__try_recursion(error_code *ec) { if (m_ec.value() == EACCES && allow_eacess) { if (ec) ec->clear(); } else { + path at_ent = std::move(curr_it.__entry_.__p_); __imp_.reset(); - set_or_throw(m_ec, ec, - "recursive_directory_iterator::operator++()"); + err.report(m_ec, "attempting recursion into \"%s\"", at_ent); } } return false; diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index 187428309..5b1f4482a 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -11,6 +11,7 @@ #define FILESYSTEM_COMMON_H #include "experimental/__config" +#include "array" #include "chrono" #include "cstdlib" #include "climits" @@ -66,26 +67,149 @@ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM namespace detail { namespace { +static std::string format_string_imp(const char* msg, ...) { + // we might need a second shot at this, so pre-emptivly make a copy + struct GuardVAList { + va_list& target; + bool active = true; + void clear() { + if (active) + va_end(target); + active = false; + } + ~GuardVAList() { + if (active) + va_end(target); + } + }; + va_list args; + va_start(args, msg); + GuardVAList args_guard = {args}; + + va_list args_cp; + va_copy(args_cp, args); + GuardVAList args_copy_guard = {args_cp}; + + std::array local_buff; + std::size_t size = local_buff.size(); + auto ret = ::vsnprintf(local_buff.data(), size, msg, args_cp); + + args_copy_guard.clear(); + + // handle empty expansion + if (ret == 0) + return std::string{}; + if (static_cast(ret) < size) + return std::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(ret) + 1; + auto buff_ptr = std::unique_ptr(new char[size]); + ret = ::vsnprintf(buff_ptr.get(), size, msg, args); + return std::string(buff_ptr.get()); +} + +const char* unwrap(string const& s) { return s.c_str(); } +const char* unwrap(path const& p) { return p.native().c_str(); } +template +Arg const& unwrap(Arg const& a) { + static_assert(!is_class::value, "cannot pass class here"); + return a; +} + +template +std::string format_string(const char* fmt, Args const&... args) { + return format_string_imp(fmt, unwrap(args)...); +} + std::error_code capture_errno() { _LIBCPP_ASSERT(errno, "Expected errno to be non-zero"); return std::error_code(errno, std::generic_category()); } -void set_or_throw(std::error_code const& m_ec, std::error_code* ec, - const char* msg, path const& p = {}, path const& p2 = {}) { - if (ec) { - *ec = m_ec; - } else { - string msg_s("std::experimental::filesystem::"); - msg_s += msg; - __throw_filesystem_error(msg_s, p, p2, m_ec); - } +template +T error_value(); +template <> +constexpr void error_value() {} +template <> +constexpr bool error_value() { + return false; } - -void set_or_throw(std::error_code* ec, const char* msg, path const& p = {}, - path const& p2 = {}) { - return set_or_throw(capture_errno(), ec, msg, p, p2); +template <> +constexpr uintmax_t error_value() { + return uintmax_t(-1); } +template <> +constexpr file_time_type error_value() { + return file_time_type::min(); +} +template <> +path error_value() { + return {}; +} + +template +struct ErrorHandler { + const char* func_name; + error_code* ec = nullptr; + const path* p1 = nullptr; + const path* p2 = nullptr; + + ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr, + const path* p2 = nullptr) + : func_name(fname), ec(ec), p1(p1), p2(p2) { + if (ec) + ec->clear(); + } + + T report(const error_code& m_ec) const { + if (ec) { + *ec = m_ec; + return error_value(); + } + string what = string("in ") + func_name; + switch (bool(p1) + bool(p2)) { + case 0: + __throw_filesystem_error(what, m_ec); + case 1: + __throw_filesystem_error(what, *p1, m_ec); + case 2: + __throw_filesystem_error(what, *p1, *p2, m_ec); + } + _LIBCPP_UNREACHABLE(); + } + + template + T report(const error_code& m_ec, const char* msg, Args const&... args) const { + if (ec) { + *ec = m_ec; + return error_value(); + } + string what = + string("in ") + func_name + ": " + format_string(msg, args...); + switch (bool(p1) + bool(p2)) { + case 0: + __throw_filesystem_error(what, m_ec); + case 1: + __throw_filesystem_error(what, *p1, m_ec); + case 2: + __throw_filesystem_error(what, *p1, *p2, m_ec); + } + _LIBCPP_UNREACHABLE(); + } + + T report(errc const& err) const { return report(make_error_code(err)); } + + template + T report(errc const& err, const char* msg, Args const&... args) const { + return report(make_error_code(err), msg, args...); + } + +private: + ErrorHandler(ErrorHandler const&) = delete; + ErrorHandler& operator=(ErrorHandler const&) = delete; +}; namespace time_util { diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index cc744fb9b..a1e88b394 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "experimental/filesystem" +#include "array" #include "iterator" #include "fstream" #include "random" /* for unique_path */ @@ -364,7 +365,8 @@ file_status create_file_status(std::error_code& m_ec, path const& p, if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { return file_status(file_type::not_found); } else if (m_ec) { - set_or_throw(m_ec, ec, "posix_stat", p); + ErrorHandler err("posix_stat", ec, &p); + err.report(m_ec, "failed to determine attributes for the specified path"); return file_status(file_type::none); } // else @@ -453,10 +455,30 @@ file_status FileDescriptor::refresh_status(std::error_code& ec) { } }} // end namespace detail -using detail::set_or_throw; -using parser::string_view_t; -using parser::PathParser; +using detail::capture_errno; +using detail::ErrorHandler; +using detail::StatT; using parser::createView; +using parser::PathParser; +using parser::string_view_t; + +void filesystem_error::__create_what(int __num_paths) { + const char* derived_what = system_error::what(); + __storage_->__what_ = [&]() -> string { + const char* p1 = path1().native().empty() ? "\"\"" : path1().c_str(); + const char* p2 = path2().native().empty() ? "\"\"" : path2().c_str(); + switch (__num_paths) { + default: + return detail::format_string("filesystem error: %s", derived_what); + case 1: + return detail::format_string("filesystem error: %s [%s]", derived_what, + p1); + case 2: + return detail::format_string("filesystem error: %s [%s] [%s]", + derived_what, p1, p2); + } + }(); +} static path __do_absolute(const path& p, path *cwd, std::error_code *ec) { if (ec) ec->clear(); @@ -476,48 +498,46 @@ path __absolute(const path& p, std::error_code *ec) { path __canonical(path const & orig_p, std::error_code *ec) { path cwd; + ErrorHandler err("canonical", ec, &orig_p, &cwd); + path p = __do_absolute(orig_p, &cwd, ec); char buff[PATH_MAX + 1]; char *ret; - if ((ret = ::realpath(p.c_str(), buff)) == nullptr) { - set_or_throw(ec, "canonical", orig_p, cwd); - return {}; - } - if (ec) ec->clear(); + if ((ret = ::realpath(p.c_str(), buff)) == nullptr) + return err.report(capture_errno()); return {ret}; } void __copy(const path& from, const path& to, copy_options options, std::error_code *ec) { - const bool sym_status = bool(options & - (copy_options::create_symlinks | copy_options::skip_symlinks)); - - const bool sym_status2 = bool(options & - copy_options::copy_symlinks); - - std::error_code m_ec1; - struct ::stat f_st = {}; - const file_status f = sym_status || sym_status2 - ? detail::posix_lstat(from, f_st, &m_ec1) - : detail::posix_stat(from, f_st, &m_ec1); - if (m_ec1) - return set_or_throw(m_ec1, ec, "copy", from, to); - - struct ::stat t_st = {}; - const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1) - : detail::posix_stat(to, t_st, &m_ec1); - - if (not status_known(t)) - return set_or_throw(m_ec1, ec, "copy", from, to); - - if (!exists(f) || is_other(f) || is_other(t) - || (is_directory(f) && is_regular_file(t)) - || detail::stat_equivalent(f_st, t_st)) - { - return set_or_throw(make_error_code(errc::function_not_supported), - ec, "copy", from, to); - } + ErrorHandler err("copy", ec, &from, &to); + + const bool sym_status = bool( + options & (copy_options::create_symlinks | copy_options::skip_symlinks)); + + const bool sym_status2 = bool(options & copy_options::copy_symlinks); + + std::error_code m_ec1; + struct ::stat f_st = {}; + const file_status f = sym_status || sym_status2 + ? detail::posix_lstat(from, f_st, &m_ec1) + : detail::posix_stat(from, f_st, &m_ec1); + if (m_ec1) + return err.report(m_ec1); + + struct ::stat t_st = {}; + const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1) + : detail::posix_stat(to, t_st, &m_ec1); + + if (not status_known(t)) + return err.report(m_ec1); + + if (!exists(f) || is_other(f) || is_other(t) || + (is_directory(f) && is_regular_file(t)) || + detail::stat_equivalent(f_st, t_st)) { + return err.report(errc::function_not_supported); + } if (ec) ec->clear(); @@ -527,8 +547,7 @@ void __copy(const path& from, const path& to, copy_options options, } else if (not exists(t)) { __copy_symlink(from, to, ec); } else { - set_or_throw(make_error_code(errc::file_exists), - ec, "copy", from, to); + return err.report(errc::file_exists); } return; } @@ -550,7 +569,7 @@ void __copy(const path& from, const path& to, copy_options options, return; } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) { - return set_or_throw(make_error_code(errc::is_a_directory), ec, "copy"); + return err.report(errc::is_a_directory); } else if (is_directory(f) && (bool(copy_options::recursive & options) || copy_options::none == options)) { @@ -565,7 +584,9 @@ void __copy(const path& from, const path& to, copy_options options, if (ec && *ec) { return; } std::error_code m_ec2; for (; it != directory_iterator(); it.increment(m_ec2)) { - if (m_ec2) return set_or_throw(m_ec2, ec, "copy", from, to); + if (m_ec2) { + return err.report(m_ec2); + } __copy(it->path(), to / it->path().filename(), options | copy_options::__in_recursive_copy, ec); if (ec && *ec) { return; } @@ -672,28 +693,20 @@ bool __copy_file(const path& from, const path& to, copy_options options, std::error_code *ec) { using detail::FileDescriptor; - using detail::StatT; - - if (ec) - ec->clear(); - - auto Error = [&](const error_code& error_ec) { - set_or_throw(error_ec, ec, "copy_file", from, to); - return false; - }; + ErrorHandler err("copy_file", ec, &to, &from); std::error_code m_ec; FileDescriptor from_fd = FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK); if (m_ec) - return Error(m_ec); + return err.report(m_ec); auto from_st = from_fd.get_status(); StatT const& from_stat = from_fd.get_stat(); if (!is_regular_file(from_st)) { if (not m_ec) m_ec = make_error_code(errc::not_supported); - return Error(m_ec); + return err.report(m_ec); } const bool skip_existing = bool(copy_options::skip_existing & options); @@ -704,14 +717,14 @@ bool __copy_file(const path& from, const path& to, copy_options options, StatT to_stat_path; file_status to_st = detail::posix_stat(to, to_stat_path, &m_ec); if (!status_known(to_st)) - return Error(m_ec); + return err.report(m_ec); const bool to_exists = exists(to_st); if (to_exists && !is_regular_file(to_st)) - return Error(make_error_code(errc::not_supported)); + return err.report(make_error_code(errc::not_supported)); if (to_exists && detail::stat_equivalent(from_stat, to_stat_path)) - return Error(make_error_code(errc::file_exists)); + return err.report(make_error_code(errc::file_exists)); if (to_exists && skip_existing) return false; @@ -729,7 +742,7 @@ bool __copy_file(const path& from, const path& to, copy_options options, } if (!to_exists || overwrite_existing) return true; - return Error(make_error_code(errc::file_exists)); + return err.report(errc::file_exists); }(); if (!ShouldCopy) return false; @@ -742,25 +755,25 @@ bool __copy_file(const path& from, const path& to, copy_options options, FileDescriptor to_fd = FileDescriptor::create_with_status( &to, m_ec, to_open_flags, from_stat.st_mode); if (m_ec) - return Error(m_ec); + return err.report(m_ec); if (to_exists) { // Check that the file we initially stat'ed is equivalent to the one // we opened. // FIXME: report this better. if (!detail::stat_equivalent(to_stat_path, to_fd.get_stat())) - return Error(make_error_code(errc::bad_file_descriptor)); + return err.report(errc::bad_file_descriptor); // Set the permissions and truncate the file we opened. if (!detail::posix_fchmod(to_fd, from_stat, m_ec)) - return Error(m_ec); + return err.report(m_ec); if (!detail::posix_ftruncate(to_fd, 0, m_ec)) - return Error(m_ec); + return err.report(m_ec); } if (!copy_file_impl(from_fd, to_fd, m_ec)) { // FIXME: Remove the dest file if we failed, and it didn't exist previously. - return Error(m_ec); + return err.report(m_ec); } return true; @@ -779,213 +792,192 @@ void __copy_symlink(const path& existing_symlink, const path& new_symlink, bool __create_directories(const path& p, std::error_code *ec) { - std::error_code m_ec; - auto const st = detail::posix_stat(p, &m_ec); - if (!status_known(st)) { - set_or_throw(m_ec, ec, "create_directories", p); - return false; - } - else if (is_directory(st)) { - if (ec) ec->clear(); - return false; - } - else if (exists(st)) { - set_or_throw(make_error_code(errc::file_exists), - ec, "create_directories", p); - return false; - } + ErrorHandler err("create_directories", ec, &p); - const path parent = p.parent_path(); - if (!parent.empty()) { - const file_status parent_st = status(parent, m_ec); - if (not status_known(parent_st)) { - set_or_throw(m_ec, ec, "create_directories", p); - return false; - } - if (not exists(parent_st)) { - __create_directories(parent, ec); - if (ec && *ec) { return false; } - } + std::error_code m_ec; + auto const st = detail::posix_stat(p, &m_ec); + if (!status_known(st)) + return err.report(m_ec); + else if (is_directory(st)) + return false; + else if (exists(st)) + return err.report(errc::file_exists); + + const path parent = p.parent_path(); + if (!parent.empty()) { + const file_status parent_st = status(parent, m_ec); + if (not status_known(parent_st)) + return err.report(m_ec); + if (not exists(parent_st)) { + __create_directories(parent, ec); + if (ec && *ec) { + return false; + } } + } return __create_directory(p, ec); } bool __create_directory(const path& p, std::error_code *ec) { - if (ec) ec->clear(); - if (::mkdir(p.c_str(), static_cast(perms::all)) == 0) - return true; - if (errno != EEXIST || !is_directory(p)) - set_or_throw(ec, "create_directory", p); - return false; + ErrorHandler err("create_directory", ec, &p); + + if (::mkdir(p.c_str(), static_cast(perms::all)) == 0) + return true; + if (errno != EEXIST || !is_directory(p)) + err.report(capture_errno()); + return false; } bool __create_directory(path const & p, path const & attributes, std::error_code *ec) { - struct ::stat attr_stat; - std::error_code mec; - auto st = detail::posix_stat(attributes, attr_stat, &mec); - if (!status_known(st)) { - set_or_throw(mec, ec, "create_directory", p, attributes); - return false; - } - if (ec) ec->clear(); - if (::mkdir(p.c_str(), attr_stat.st_mode) == 0) - return true; - if (errno != EEXIST || !is_directory(p)) - set_or_throw(ec, "create_directory", p, attributes); - return false; + ErrorHandler err("create_directory", ec, &p, &attributes); + + StatT attr_stat; + std::error_code mec; + auto st = detail::posix_stat(attributes, attr_stat, &mec); + if (!status_known(st)) + return err.report(mec); + + if (::mkdir(p.c_str(), attr_stat.st_mode) == 0) + return true; + if (errno != EEXIST || !is_directory(p)) + err.report(capture_errno()); + return false; } -void __create_directory_symlink(path const & from, path const & to, - std::error_code *ec){ - if (::symlink(from.c_str(), to.c_str()) != 0) - set_or_throw(ec, "create_directory_symlink", from, to); - else if (ec) - ec->clear(); +void __create_directory_symlink(path const& from, path const& to, + std::error_code* ec) { + ErrorHandler err("create_directory_symlink", ec, &from, &to); + if (::symlink(from.c_str(), to.c_str()) != 0) + return err.report(capture_errno()); } void __create_hard_link(const path& from, const path& to, std::error_code *ec){ - if (::link(from.c_str(), to.c_str()) == -1) - set_or_throw(ec, "create_hard_link", from, to); - else if (ec) - ec->clear(); + ErrorHandler err("create_hard_link", ec, &from, &to); + if (::link(from.c_str(), to.c_str()) == -1) + return err.report(capture_errno()); } void __create_symlink(path const & from, path const & to, std::error_code *ec) { - - if (::symlink(from.c_str(), to.c_str()) == -1) - set_or_throw(ec, "create_symlink", from, to); - else if (ec) - ec->clear(); + ErrorHandler err("create_symlink", ec, &from, &to); + if (::symlink(from.c_str(), to.c_str()) == -1) + return err.report(capture_errno()); } path __current_path(std::error_code *ec) { - auto size = ::pathconf(".", _PC_PATH_MAX); - _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size"); + ErrorHandler err("current_path", ec); - auto buff = std::unique_ptr(new char[size + 1]); - char* ret; - if ((ret = ::getcwd(buff.get(), static_cast(size))) == nullptr) { - set_or_throw(ec, "current_path"); - return {}; - } - if (ec) ec->clear(); - return {buff.get()}; + auto size = ::pathconf(".", _PC_PATH_MAX); + _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size"); + + auto buff = std::unique_ptr(new char[size + 1]); + char* ret; + if ((ret = ::getcwd(buff.get(), static_cast(size))) == nullptr) + return err.report(capture_errno(), "call to getcwd failed"); + + return {buff.get()}; } void __current_path(const path& p, std::error_code *ec) { - if (::chdir(p.c_str()) == -1) - set_or_throw(ec, "current_path", p); - else if (ec) - ec->clear(); + ErrorHandler err("current_path", ec, &p); + if (::chdir(p.c_str()) == -1) + err.report(capture_errno()); } bool __equivalent(const path& p1, const path& p2, std::error_code *ec) { - auto make_unsupported_error = [&]() { - set_or_throw(make_error_code(errc::not_supported), ec, - "equivalent", p1, p2); - return false; - }; - std::error_code ec1, ec2; - struct ::stat st1 = {}; - struct ::stat st2 = {}; - auto s1 = detail::posix_stat(p1.native(), st1, &ec1); - if (!exists(s1)) - return make_unsupported_error(); - auto s2 = detail::posix_stat(p2.native(), st2, &ec2); - if (!exists(s2)) - return make_unsupported_error(); - if (ec) ec->clear(); - return detail::stat_equivalent(st1, st2); + ErrorHandler err("equivalent", ec, &p1, &p2); + + std::error_code ec1, ec2; + StatT st1 = {}, st2 = {}; + auto s1 = detail::posix_stat(p1.native(), st1, &ec1); + if (!exists(s1)) + return err.report(errc::not_supported); + auto s2 = detail::posix_stat(p2.native(), st2, &ec2); + if (!exists(s2)) + return err.report(errc::not_supported); + + return detail::stat_equivalent(st1, st2); } std::uintmax_t __file_size(const path& p, std::error_code *ec) { - std::error_code m_ec; - struct ::stat st; - file_status fst = detail::posix_stat(p, st, &m_ec); - if (!exists(fst) || !is_regular_file(fst)) { - errc error_kind = - is_directory(fst) ? errc::is_a_directory : errc::not_supported; - if (!m_ec) - m_ec = make_error_code(error_kind); - set_or_throw(m_ec, ec, "file_size", p); - return static_cast(-1); - } + ErrorHandler err("file_size", ec, &p); + + std::error_code m_ec; + struct ::stat st; + file_status fst = detail::posix_stat(p, st, &m_ec); + if (!exists(fst) || !is_regular_file(fst)) { + errc error_kind = + is_directory(fst) ? errc::is_a_directory : errc::not_supported; + if (!m_ec) + m_ec = make_error_code(error_kind); + return err.report(m_ec); + } // is_regular_file(p) == true - if (ec) ec->clear(); return static_cast(st.st_size); } std::uintmax_t __hard_link_count(const path& p, std::error_code *ec) { - std::error_code m_ec; - struct ::stat st; - detail::posix_stat(p, st, &m_ec); - if (m_ec) { - set_or_throw(m_ec, ec, "hard_link_count", p); - return static_cast(-1); - } - if (ec) ec->clear(); - return static_cast(st.st_nlink); + ErrorHandler err("hard_link_count", ec, &p); + + std::error_code m_ec; + StatT st; + detail::posix_stat(p, st, &m_ec); + if (m_ec) + return err.report(m_ec); + return static_cast(st.st_nlink); } bool __fs_is_empty(const path& p, std::error_code *ec) { - if (ec) ec->clear(); - std::error_code m_ec; - struct ::stat pst; - auto st = detail::posix_stat(p, pst, &m_ec); - if (m_ec) { - set_or_throw(m_ec, ec, "is_empty", p); - return false; - } - else if (!is_directory(st) && !is_regular_file(st)) { - m_ec = make_error_code(errc::not_supported); - set_or_throw(m_ec, ec, "is_empty"); - return false; - } - else if (is_directory(st)) { - auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p); - if (ec && *ec) - return false; - return it == directory_iterator{}; - } - else if (is_regular_file(st)) - return static_cast(pst.st_size) == 0; + ErrorHandler err("is_empty", ec, &p); - _LIBCPP_UNREACHABLE(); + std::error_code m_ec; + StatT pst; + auto st = detail::posix_stat(p, pst, &m_ec); + if (m_ec) + return err.report(m_ec); + else if (!is_directory(st) && !is_regular_file(st)) + return err.report(errc::not_supported); + else if (is_directory(st)) { + auto it = ec ? directory_iterator(p, *ec) : directory_iterator(p); + if (ec && *ec) + return false; + return it == directory_iterator{}; + } else if (is_regular_file(st)) + return static_cast(pst.st_size) == 0; + + _LIBCPP_UNREACHABLE(); } -static file_time_type __extract_last_write_time(const path& p, - const struct ::stat& st, +static file_time_type __extract_last_write_time(const path& p, const StatT& st, error_code* ec) { using detail::FSTime; + ErrorHandler err("last_write_time", ec, &p); + auto ts = detail::extract_mtime(st); - if (!FSTime::is_representable(ts)) { - set_or_throw(make_error_code(errc::value_too_large), ec, "last_write_time", - p); - return file_time_type::min(); - } + if (!FSTime::is_representable(ts)) + return err.report(errc::value_too_large); + return FSTime::convert_timespec(ts); } file_time_type __last_write_time(const path& p, std::error_code *ec) { using namespace ::std::chrono; + ErrorHandler err("last_write_time", ec, &p); + std::error_code m_ec; - struct ::stat st; + StatT st; detail::posix_stat(p, st, &m_ec); - if (m_ec) { - set_or_throw(m_ec, ec, "last_write_time", p); - return file_time_type::min(); - } - if (ec) ec->clear(); + if (m_ec) + return err.report(m_ec); return __extract_last_write_time(p, st, ec); } @@ -995,6 +987,8 @@ void __last_write_time(const path& p, file_time_type new_time, using namespace std::chrono; using namespace detail; + ErrorHandler err("last_write_time", ec, &p); + std::error_code m_ec; TimeStructArray tbuf; #if !defined(_LIBCXX_USE_UTIMENSAT) @@ -1003,99 +997,92 @@ void __last_write_time(const path& p, file_time_type new_time, // ::utimes struct ::stat st; file_status fst = detail::posix_stat(p, st, &m_ec); - if (m_ec && !status_known(fst)) { - set_or_throw(m_ec, ec, "last_write_time", p); - return; - } + if (m_ec && !status_known(fst)) + return err.report(m_ec); SetTimeStructTo(tbuf[0], detail::extract_atime(st)); #else tbuf[0].tv_sec = 0; tbuf[0].tv_nsec = UTIME_OMIT; #endif - if (SetTimeStructTo(tbuf[1], new_time)) { - set_or_throw(make_error_code(errc::invalid_argument), ec, - "last_write_time", p); - return; - } + if (SetTimeStructTo(tbuf[1], new_time)) + return err.report(errc::invalid_argument); SetFileTimes(p, tbuf, m_ec); if (m_ec) - set_or_throw(m_ec, ec, "last_write_time", p); - else if (ec) - ec->clear(); + return err.report(m_ec); } void __permissions(const path& p, perms prms, perm_options opts, std::error_code *ec) { - auto has_opt = [&](perm_options o) { return bool(o & opts); }; - const bool resolve_symlinks = !has_opt(perm_options::nofollow); - const bool add_perms = has_opt(perm_options::add); - const bool remove_perms = has_opt(perm_options::remove); - _LIBCPP_ASSERT( - (add_perms + remove_perms + has_opt(perm_options::replace)) == 1, - "One and only one of the perm_options constants replace, add, or remove " - "is present in opts"); - - bool set_sym_perms = false; - prms &= perms::mask; - if (!resolve_symlinks || (add_perms || remove_perms)) { - std::error_code m_ec; - file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec) - : detail::posix_lstat(p, &m_ec); - set_sym_perms = is_symlink(st); - if (m_ec) return set_or_throw(m_ec, ec, "permissions", p); - _LIBCPP_ASSERT(st.permissions() != perms::unknown, - "Permissions unexpectedly unknown"); - if (add_perms) - prms |= st.permissions(); - else if (remove_perms) - prms = st.permissions() & ~prms; - } + ErrorHandler err("permissions", ec, &p); + + auto has_opt = [&](perm_options o) { return bool(o & opts); }; + const bool resolve_symlinks = !has_opt(perm_options::nofollow); + const bool add_perms = has_opt(perm_options::add); + const bool remove_perms = has_opt(perm_options::remove); + _LIBCPP_ASSERT( + (add_perms + remove_perms + has_opt(perm_options::replace)) == 1, + "One and only one of the perm_options constants replace, add, or remove " + "is present in opts"); + + bool set_sym_perms = false; + prms &= perms::mask; + if (!resolve_symlinks || (add_perms || remove_perms)) { + std::error_code m_ec; + file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec) + : detail::posix_lstat(p, &m_ec); + set_sym_perms = is_symlink(st); + if (m_ec) + return err.report(m_ec); + _LIBCPP_ASSERT(st.permissions() != perms::unknown, + "Permissions unexpectedly unknown"); + if (add_perms) + prms |= st.permissions(); + else if (remove_perms) + prms = st.permissions() & ~prms; + } const auto real_perms = detail::posix_convert_perms(prms); # if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0; if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { - return set_or_throw(ec, "permissions", p); + return err.report(capture_errno()); } # else if (set_sym_perms) - return set_or_throw(make_error_code(errc::operation_not_supported), - ec, "permissions", p); + return err.report(errc::operation_not_supported); if (::chmod(p.c_str(), real_perms) == -1) { - return set_or_throw(ec, "permissions", p); + return err.report(capture_errno()); } # endif - if (ec) ec->clear(); } path __read_symlink(const path& p, std::error_code *ec) { - char buff[PATH_MAX + 1]; - std::error_code m_ec; - ::ssize_t ret; - if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) { - set_or_throw(ec, "read_symlink", p); - return {}; - } + ErrorHandler err("read_symlink", ec, &p); + + char buff[PATH_MAX + 1]; + std::error_code m_ec; + ::ssize_t ret; + if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) { + return err.report(capture_errno()); + } _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO"); _LIBCPP_ASSERT(ret > 0, "TODO"); - if (ec) ec->clear(); buff[ret] = 0; return {buff}; } bool __remove(const path& p, std::error_code *ec) { - if (ec) ec->clear(); - - if (::remove(p.c_str()) == -1) { - if (errno != ENOENT) - set_or_throw(ec, "remove", p); - return false; - } + ErrorHandler err("remove", ec, &p); + if (::remove(p.c_str()) == -1) { + if (errno != ENOENT) + err.report(capture_errno()); + return false; + } return true; } @@ -1123,45 +1110,39 @@ std::uintmax_t remove_all_impl(path const & p, std::error_code& ec) } // end namespace std::uintmax_t __remove_all(const path& p, std::error_code *ec) { - if (ec) ec->clear(); - - std::error_code mec; - auto count = remove_all_impl(p, mec); - if (mec) { - if (mec == errc::no_such_file_or_directory) { - return 0; - } else { - set_or_throw(mec, ec, "remove_all", p); - return static_cast(-1); - } - } + ErrorHandler err("remove_all", ec, &p); + + std::error_code mec; + auto count = remove_all_impl(p, mec); + if (mec) { + if (mec == errc::no_such_file_or_directory) + return 0; + return err.report(mec); + } return count; } void __rename(const path& from, const path& to, std::error_code *ec) { - if (::rename(from.c_str(), to.c_str()) == -1) - set_or_throw(ec, "rename", from, to); - else if (ec) - ec->clear(); + ErrorHandler err("rename", ec, &from, &to); + if (::rename(from.c_str(), to.c_str()) == -1) + err.report(capture_errno()); } void __resize_file(const path& p, std::uintmax_t size, std::error_code *ec) { - if (::truncate(p.c_str(), static_cast<::off_t>(size)) == -1) - set_or_throw(ec, "resize_file", p); - else if (ec) - ec->clear(); + ErrorHandler err("resize_file", ec, &p); + if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) + return err.report(capture_errno()); } space_info __space(const path& p, std::error_code *ec) { - space_info si; - struct statvfs m_svfs = {}; - if (::statvfs(p.c_str(), &m_svfs) == -1) { - set_or_throw(ec, "space", p); - si.capacity = si.free = si.available = - static_cast(-1); - return si; - } - if (ec) ec->clear(); + ErrorHandler err("space", ec, &p); + space_info si; + struct statvfs m_svfs = {}; + if (::statvfs(p.c_str(), &m_svfs) == -1) { + err.report(capture_errno()); + si.capacity = si.free = si.available = static_cast(-1); + return si; + } // Multiply with overflow checking. auto do_mult = [&](std::uintmax_t& out, std::uintmax_t other) { out = other * m_svfs.f_frsize; @@ -1183,6 +1164,8 @@ file_status __symlink_status(const path& p, std::error_code *ec) { } path __temp_directory_path(std::error_code* ec) { + ErrorHandler err("temp_directory_path", ec); + const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; const char* ret = nullptr; @@ -1194,20 +1177,21 @@ path __temp_directory_path(std::error_code* ec) { path p(ret); std::error_code m_ec; - if (!exists(p, m_ec) || !is_directory(p, m_ec)) { - if (!m_ec || m_ec == make_error_code(errc::no_such_file_or_directory)) - m_ec = make_error_code(errc::not_a_directory); - set_or_throw(m_ec, ec, "temp_directory_path"); - return {}; - } + file_status st = detail::posix_stat(p, &m_ec); + if (!status_known(st)) + return err.report(m_ec, "cannot access path \"%s\"", p); + + if (!exists(st) || !is_directory(st)) + return err.report(errc::not_a_directory, "path \"%s\" is not a directory", + p); - if (ec) - ec->clear(); return p; } path __weakly_canonical(const path& p, std::error_code *ec) { + ErrorHandler err("weakly_canonical", ec, &p); + if (p.empty()) return __canonical("", ec); @@ -1223,8 +1207,7 @@ path __weakly_canonical(const path& p, std::error_code *ec) { std::error_code m_ec; file_status st = __status(tmp, &m_ec); if (!status_known(st)) { - set_or_throw(m_ec, ec, "weakly_canonical", p); - return {}; + return err.report(m_ec); } else if (exists(st)) { result = __canonical(tmp, ec); break; diff --git a/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp b/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp index 30b44b877..2305f54f5 100644 --- a/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp +++ b/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp @@ -80,7 +80,8 @@ TEST_CASE(last_write_time_not_representable_error) { TEST_CHECK(last_write_time(file, ec) == file_time_type::min()); TEST_CHECK(ErrorIs(ec, expected_err)); - ExceptionChecker CheckExcept(file, expected_err); + ExceptionChecker CheckExcept(file, expected_err, + "directory_entry::last_write_time"); TEST_CHECK_THROW_RESULT(fs::filesystem_error, CheckExcept, ent.last_write_time()); diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp index 40d2cef1d..74c73f030 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp @@ -168,7 +168,8 @@ TEST_CASE(refresh_cannot_resolve) { TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); TEST_CHECK(ent.path() == file); - ExceptionChecker Checker(file, std::errc::permission_denied); + ExceptionChecker Checker(file, std::errc::permission_denied, + "directory_entry::refresh"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.refresh()); } permissions(dir, old_perms); @@ -182,7 +183,8 @@ TEST_CASE(refresh_cannot_resolve) { TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); TEST_CHECK(ent.path() == sym_in_dir); - ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied); + ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied, + "directory_entry::refresh"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.refresh()); } permissions(dir, old_perms); diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp index d5050edc7..a38b10c00 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp @@ -102,7 +102,7 @@ TEST_CASE(not_regular_file) { TEST_CHECK(ec == other_ec); TEST_CHECK(ErrorIs(ec, TC.expected_err)); - ExceptionChecker Checker(p, TC.expected_err); + ExceptionChecker Checker(p, TC.expected_err, "directory_entry::file_size"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); } } @@ -134,7 +134,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); ExceptionChecker Checker(StaticEnv::DNE, - std::errc::no_such_file_or_directory); + std::errc::no_such_file_or_directory, + "directory_entry::file_size"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); } // test a dead symlink @@ -156,7 +157,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); ExceptionChecker Checker(StaticEnv::BadSymlink, - std::errc::no_such_file_or_directory); + std::errc::no_such_file_or_directory, + "directory_entry::file_size"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); } // test a file w/o appropriate permissions. @@ -174,7 +176,7 @@ TEST_CASE(error_reporting) { TEST_CHECK(ent.file_size(ec) == uintmax_t(-1)); TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); - ExceptionChecker Checker(file, std::errc::permission_denied); + ExceptionChecker Checker(file, std::errc::permission_denied, "file_size"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); permissions(dir, old_perms); @@ -199,7 +201,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ent.file_size(ec) == uintmax_t(-1)); TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); - ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied); + ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied, + "file_size"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); permissions(dir, old_perms); @@ -224,7 +227,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ent.file_size(ec) == uintmax_t(-1)); TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); - ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied); + ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied, + "file_size"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.file_size()); permissions(dir, old_perms); diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp index 0ec801bb4..d11457d20 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp @@ -133,7 +133,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); ExceptionChecker Checker(StaticEnv::DNE, - std::errc::no_such_file_or_directory); + std::errc::no_such_file_or_directory, + "directory_entry::hard_link_count"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count()); } // test a dead symlink @@ -155,7 +156,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); ExceptionChecker Checker(StaticEnv::BadSymlink, - std::errc::no_such_file_or_directory); + std::errc::no_such_file_or_directory, + "directory_entry::hard_link_count"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count()); } // test a file w/o appropriate permissions. @@ -173,7 +175,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1)); TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); - ExceptionChecker Checker(file, std::errc::permission_denied); + ExceptionChecker Checker(file, std::errc::permission_denied, + "hard_link_count"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count()); permissions(dir, old_perms); @@ -198,7 +201,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1)); TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); - ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied); + ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied, + "hard_link_count"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count()); permissions(dir, old_perms); @@ -223,7 +227,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ent.hard_link_count(ec) == uintmax_t(-1)); TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); - ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied); + ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied, + "hard_link_count"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.hard_link_count()); permissions(dir, old_perms); diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp index 250dc6f5a..3d519728c 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp +++ b/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp @@ -106,7 +106,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); ExceptionChecker Checker(StaticEnv::DNE, - std::errc::no_such_file_or_directory); + std::errc::no_such_file_or_directory, + "directory_entry::last_write_time"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time()); } // test a dead symlink @@ -128,7 +129,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); ExceptionChecker Checker(StaticEnv::BadSymlink, - std::errc::no_such_file_or_directory); + std::errc::no_such_file_or_directory, + "directory_entry::last_write_time"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time()); } // test a file w/o appropriate permissions. @@ -146,7 +148,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ent.last_write_time(ec) == file_time_type::min()); TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); - ExceptionChecker Checker(file, std::errc::permission_denied); + ExceptionChecker Checker(file, std::errc::permission_denied, + "last_write_time"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time()); permissions(dir, old_perms); @@ -171,7 +174,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ent.last_write_time(ec) == file_time_type::min()); TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); - ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied); + ExceptionChecker Checker(sym_in_dir, std::errc::permission_denied, + "last_write_time"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time()); permissions(dir, old_perms); @@ -196,7 +200,8 @@ TEST_CASE(error_reporting) { TEST_CHECK(ent.last_write_time(ec) == file_time_type::min()); TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); - ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied); + ExceptionChecker Checker(sym_out_of_dir, std::errc::permission_denied, + "last_write_time"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ent.last_write_time()); permissions(dir, old_perms); diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp b/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp index 1699a414a..830f4a943 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp +++ b/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp @@ -25,6 +25,8 @@ #include "rapid-cxx-test.hpp" #include "filesystem_test_helper.hpp" +#include + using namespace fs; TEST_SUITE(recursive_directory_iterator_increment_tests) @@ -290,18 +292,15 @@ TEST_CASE(test_PR35078) } { bool SeenNestedFile = false; - recursive_directory_iterator it = SetupState(true, SeenNestedFile); + recursive_directory_iterator it = SetupState(false, SeenNestedFile); TEST_REQUIRE(it != endIt); TEST_REQUIRE(*it == nestedDir); - ec = GetTestEC(); - it.increment(ec); - TEST_CHECK(!ec); - if (SeenNestedFile) { - TEST_CHECK(it == endIt); - } else { - TEST_REQUIRE(it != endIt); - TEST_CHECK(*it == nestedFile); - } + + ExceptionChecker Checker(std::errc::permission_denied, + "recursive_directory_iterator::operator++()", + format_string("attempting recursion into \"%s\"", + nestedDir.native())); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, ++it); } } diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp index 3c2543ab9..5f023743a 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp @@ -64,7 +64,7 @@ TEST_CASE(test_error_reporting) { TEST_CHECK(fs::copy_file(file, file, copy_options::overwrite_existing, ec) == false); TEST_CHECK(ErrorIs(ec, std::errc::file_exists)); - ExceptionChecker Checker(file, file, std::errc::file_exists); + ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing)); } @@ -72,7 +72,7 @@ TEST_CASE(test_error_reporting) { std::error_code ec; TEST_CHECK(fs::copy_file(file, file2, ec) == false); TEST_CHECK(ErrorIs(ec, std::errc::file_exists)); - ExceptionChecker Checker(file, file, std::errc::file_exists); + ExceptionChecker Checker(file, file, std::errc::file_exists, "copy_file"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, copy_file(file, file, copy_options::overwrite_existing)); } diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp index e2b2513ec..c79012d9e 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp @@ -69,14 +69,15 @@ TEST_CASE(file_size_error_cases) {StaticEnv::Dir, std::errc::is_a_directory}, {StaticEnv::SymlinkToDir, std::errc::is_a_directory}, {StaticEnv::BadSymlink, std::errc::no_such_file_or_directory}, - {StaticEnv::DNE, std::errc::no_such_file_or_directory}}; + {StaticEnv::DNE, std::errc::no_such_file_or_directory}, + {"", std::errc::no_such_file_or_directory}}; const uintmax_t expect = static_cast(-1); for (auto& TC : TestCases) { std::error_code ec = GetTestEC(); TEST_CHECK(file_size(TC.p, ec) == expect); TEST_CHECK(ErrorIs(ec, TC.expected_err)); - ExceptionChecker Checker(TC.p, TC.expected_err); + ExceptionChecker Checker(TC.p, TC.expected_err, "file_size"); TEST_CHECK_THROW_RESULT(filesystem_error, Checker, file_size(TC.p)); } } diff --git a/test/support/filesystem_test_helper.hpp b/test/support/filesystem_test_helper.hpp index de06868c0..f02792870 100644 --- a/test/support/filesystem_test_helper.hpp +++ b/test/support/filesystem_test_helper.hpp @@ -9,8 +9,11 @@ #include #include #include +#include +#include "test_macros.h" #include "rapid-cxx-test.hpp" +#include "format_string.hpp" // static test helpers @@ -442,25 +445,77 @@ inline bool PathEq(fs::path const& LHS, fs::path const& RHS) { } struct ExceptionChecker { - std::vector expected_err_list; + std::errc expected_err; fs::path expected_path1; fs::path expected_path2; + unsigned num_paths; + const char* func_name; + std::string opt_message; + + explicit ExceptionChecker(std::errc first_err, const char* func_name, + std::string opt_msg = {}) + : expected_err{first_err}, num_paths(0), func_name(func_name), + opt_message(opt_msg) {} + explicit ExceptionChecker(fs::path p, std::errc first_err, + const char* func_name, std::string opt_msg = {}) + : expected_err(first_err), expected_path1(p), num_paths(1), + func_name(func_name), opt_message(opt_msg) {} - template - explicit ExceptionChecker(fs::path p, std::errc first_err, ErrcT... rest_err) - : expected_err_list({first_err, rest_err...}), expected_path1(p) {} - - template explicit ExceptionChecker(fs::path p1, fs::path p2, std::errc first_err, - ErrcT... rest_err) - : expected_err_list({first_err, rest_err...}), expected_path1(p1), - expected_path2(p2) {} + const char* func_name, std::string opt_msg = {}) + : expected_err(first_err), expected_path1(p1), expected_path2(p2), + num_paths(2), func_name(func_name), opt_message(opt_msg) {} - void operator()(fs::filesystem_error const& Err) const { - TEST_CHECK(ErrorIsImp(Err.code(), expected_err_list)); + void operator()(fs::filesystem_error const& Err) { + TEST_CHECK(ErrorIsImp(Err.code(), {expected_err})); TEST_CHECK(Err.path1() == expected_path1); TEST_CHECK(Err.path2() == expected_path2); + LIBCPP_ONLY(check_libcxx_string(Err)); + } + + void check_libcxx_string(fs::filesystem_error const& Err) { + std::string message = std::make_error_code(expected_err).message(); + + std::string additional_msg = ""; + if (!opt_message.empty()) { + additional_msg = opt_message + ": "; + } + auto transform_path = [](const fs::path& p) { + if (p.native().empty()) + return "\"\""; + return p.c_str(); + }; + std::string format = [&]() -> std::string { + switch (num_paths) { + case 0: + return format_string("filesystem error: in %s: %s%s", func_name, + additional_msg, message); + case 1: + return format_string("filesystem error: in %s: %s%s [%s]", func_name, + additional_msg, message, + transform_path(expected_path1)); + case 2: + return format_string("filesystem error: in %s: %s%s [%s] [%s]", + func_name, additional_msg, message, + transform_path(expected_path1), + transform_path(expected_path2)); + default: + TEST_CHECK(false && "unexpected case"); + return ""; + } + }(); + TEST_CHECK(format == Err.what()); + if (format != Err.what()) { + fprintf(stderr, + "filesystem_error::what() does not match expected output:\n"); + fprintf(stderr, " expected: \"%s\"\n", format.c_str()); + fprintf(stderr, " actual: \"%s\"\n\n", Err.what()); + } } + + ExceptionChecker(ExceptionChecker const&) = delete; + ExceptionChecker& operator=(ExceptionChecker const&) = delete; + }; #endif /* FILESYSTEM_TEST_HELPER_HPP */ diff --git a/test/support/format_string.hpp b/test/support/format_string.hpp new file mode 100644 index 000000000..ea3116fac --- /dev/null +++ b/test/support/format_string.hpp @@ -0,0 +1,68 @@ +#ifndef TEST_SUPPORT_FORMAT_STRING_HPP +#define TEST_SUPPORT_FORMAT_STRING_HPP + +#include +#include +#include +#include + +namespace format_string_detail { +inline std::string format_string_imp(const char* msg, ...) { + // we might need a second shot at this, so pre-emptivly make a copy + struct GuardVAList { + va_list& target; + bool active = true; + void clear() { + if (active) + va_end(target); + active = false; + } + ~GuardVAList() { + if (active) + va_end(target); + } + }; + va_list args; + va_start(args, msg); + GuardVAList args_guard = {args}; + + va_list args_cp; + va_copy(args_cp, args); + GuardVAList args_copy_guard = {args_cp}; + + std::array local_buff; + std::size_t size = local_buff.size(); + auto ret = ::vsnprintf(local_buff.data(), size, msg, args_cp); + + args_copy_guard.clear(); + + // handle empty expansion + if (ret == 0) + return std::string{}; + if (static_cast(ret) < size) + return std::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(ret) + 1; + auto buff_ptr = std::unique_ptr(new char[size]); + ret = ::vsnprintf(buff_ptr.get(), size, msg, args); + return std::string(buff_ptr.get()); +} + +const char* unwrap(std::string& s) { return s.c_str(); } +template +Arg const& unwrap(Arg& a) { + static_assert(!std::is_class::value, "cannot pass class here"); + return a; +} + +} // namespace format_string_detail + +template +std::string format_string(const char* fmt, Args const&... args) { + return format_string_detail::format_string_imp( + fmt, format_string_detail::unwrap(const_cast(args))...); +} + +#endif // TEST_SUPPORT_FORMAT_STRING_HPP diff --git a/www/cxx2a_status.html b/www/cxx2a_status.html index 6b486bb62..6b2d29e5d 100644 --- a/www/cxx2a_status.html +++ b/www/cxx2a_status.html @@ -151,7 +151,7 @@ 2953LWG 2853 should apply to deque::erase tooAlbuquerque 2958Moves improperly defined as deletedAlbuquerque 2964Apparently redundant requirement for dynamic_pointer_castAlbuquerque - 2965Non-existing path::native_string() in filesystem_error::what() specificationAlbuquerque + 2965Non-existing path::native_string() in filesystem_error::what() specificationAlbuquerqueNothing to do 2972What is is_trivially_destructible_v<int>?AlbuquerqueComplete 2976Dangling uses_allocator specialization for packaged_taskAlbuquerqueComplete 2977unordered_meow::merge() has incorrect Throws: clauseAlbuquerque @@ -196,7 +196,7 @@ 3039Unnecessary decay in thread and packaged_taskJacksonvilleComplete 3041Unnecessary decay in reference_wrapperJacksonvilleComplete 3042is_literal_type_v should be inlineJacksonvilleComplete - 3043Bogus postcondition for filesystem_error constructorJacksonville + 3043Bogus postcondition for filesystem_error constructorJacksonvilleComplete 3045atomic<floating-point> doesn't have value_type or difference_typeJacksonville 3048transform_reduce(exec, first1, last1, first2, init) discards execution policyJacksonville 3051Floating point classifications were inadvertently changed in P0175JacksonvilleNothing to do -- GitLab From a0a39e593e32bf9d8c1dd7a5595c32538a843c00 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 23 Jul 2018 03:06:57 +0000 Subject: [PATCH 049/495] Work around various GCC 4.9 build errors git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337665 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/filesystem_common.h | 15 +++++++-------- src/experimental/filesystem/operations.cpp | 8 +++++++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index 5b1f4482a..6db0cac7f 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -72,6 +72,7 @@ static std::string format_string_imp(const char* msg, ...) { struct GuardVAList { va_list& target; bool active = true; + GuardVAList(va_list &target) : target(target), active(true) {} void clear() { if (active) va_end(target); @@ -84,11 +85,11 @@ static std::string format_string_imp(const char* msg, ...) { }; va_list args; va_start(args, msg); - GuardVAList args_guard = {args}; + GuardVAList args_guard(args); va_list args_cp; va_copy(args_cp, args); - GuardVAList args_copy_guard = {args_cp}; + GuardVAList args_copy_guard(args_cp); std::array local_buff; std::size_t size = local_buff.size(); @@ -131,7 +132,7 @@ std::error_code capture_errno() { template T error_value(); template <> -constexpr void error_value() {} +_LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value() {} template <> constexpr bool error_value() { return false; @@ -141,7 +142,7 @@ constexpr uintmax_t error_value() { return uintmax_t(-1); } template <> -constexpr file_time_type error_value() { +_LIBCPP_CONSTEXPR_AFTER_CXX11 file_time_type error_value() { return file_time_type::min(); } template <> @@ -369,7 +370,7 @@ TimeSpec extract_atime(StatT const& st) { return st.st_atim; } using TimeStruct = struct ::timeval; using TimeStructArray = TimeStruct[2]; #else -using TimeStruct = struct ::timespec; +using TimeStruct = TimeSpec; using TimeStructArray = TimeStruct[2]; #endif @@ -413,8 +414,6 @@ bool SetTimeStructTo(TimeStruct& TS, file_time_type NewTime) { _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#endif + #endif // FILESYSTEM_COMMON_H diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index a1e88b394..a3dd4349d 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -36,6 +36,12 @@ # define _LIBCPP_USE_COPYFILE #endif +#if defined(_LIBCPP_COMPILER_GCC) +#if _GNUC_VER < 500 +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif +#endif + _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM filesystem_error::~filesystem_error() {} @@ -446,7 +452,7 @@ bool stat_equivalent(const StatT& st1, const StatT& st2) { file_status FileDescriptor::refresh_status(std::error_code& ec) { // FD must be open and good. m_status = file_status{}; - m_stat = StatT{}; + m_stat = {}; std::error_code m_ec; if (::fstat(fd, &m_stat) == -1) m_ec = capture_errno(); -- GitLab From ba01d96cb5a7051960219106c8c254509976fd44 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 23 Jul 2018 03:41:46 +0000 Subject: [PATCH 050/495] Fix use of C++14 syntax in C++11 filesystem tests. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337666 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/support/format_string.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/support/format_string.hpp b/test/support/format_string.hpp index ea3116fac..17e467c8c 100644 --- a/test/support/format_string.hpp +++ b/test/support/format_string.hpp @@ -11,7 +11,9 @@ inline std::string format_string_imp(const char* msg, ...) { // we might need a second shot at this, so pre-emptivly make a copy struct GuardVAList { va_list& target; - bool active = true; + bool active; + GuardVAList(va_list& target) : target(target), active(true) {} + void clear() { if (active) va_end(target); @@ -24,11 +26,11 @@ inline std::string format_string_imp(const char* msg, ...) { }; va_list args; va_start(args, msg); - GuardVAList args_guard = {args}; + GuardVAList args_guard(args); va_list args_cp; va_copy(args_cp, args); - GuardVAList args_copy_guard = {args_cp}; + GuardVAList args_copy_guard(args_cp); std::array local_buff; std::size_t size = local_buff.size(); -- GitLab From 24acfd881a8f0573f6f5a1e2c2617beb6d0be974 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Mon, 23 Jul 2018 04:19:55 +0000 Subject: [PATCH 051/495] [CMake] Support statically linking dependencies only to shared or static library Currently it's possible to select whether to statically link unwinder or the C++ ABI library, but this option applies to both the shared and static library. However, in some scenarios it may be desirable to only statically link unwinder and C++ ABI library into static C++ library since for shared C++ library we can rely on dynamic linking and linker scripts. This change enables selectively enabling or disabling statically linking only to shared or static library. Differential Revision: https://reviews.llvm.org/D49502 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337668 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 8 ++++++++ cmake/Modules/HandleLibCXXABI.cmake | 6 +++--- lib/CMakeLists.txt | 6 +++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6521ebbe4..df59b5610 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,14 @@ endif() # cannot be used with LIBCXX_ENABLE_ABI_LINKER_SCRIPT. option(LIBCXX_ENABLE_STATIC_ABI_LIBRARY "Statically link the ABI library" OFF) +cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY + "Statically link the ABI library to static library" ON + "LIBCXX_ENABLE_STATIC_ABI_LIBRARY;LIBCXX_ENABLE_STATIC" OFF) + +cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY + "Statically link the ABI library to shared library" ON + "LIBCXX_ENABLE_STATIC_ABI_LIBRARY;LIBCXX_ENABLE_STATIC" OFF) + # Generate and install a linker script inplace of libc++.so. The linker script # will link libc++ to the correct ABI library. This option is on by default # on UNIX platforms other than Apple unless 'LIBCXX_ENABLE_STATIC_ABI_LIBRARY' diff --git a/cmake/Modules/HandleLibCXXABI.cmake b/cmake/Modules/HandleLibCXXABI.cmake index 0eb70a739..d837c3c37 100644 --- a/cmake/Modules/HandleLibCXXABI.cmake +++ b/cmake/Modules/HandleLibCXXABI.cmake @@ -96,10 +96,10 @@ if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++" OR elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi") if (LIBCXX_CXX_ABI_INTREE) # Link against just-built "cxxabi" target. - if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) - set(CXXABI_LIBNAME cxxabi_static) + if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY) + set(CXXABI_LIBNAME cxxabi_static) else() - set(CXXABI_LIBNAME cxxabi_shared) + set(CXXABI_LIBNAME cxxabi_shared) endif() set(LIBCXX_LIBCPPABI_VERSION "2" PARENT_SCOPE) else() diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index d32f8fb8e..5ac691a75 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -44,7 +44,7 @@ if (APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR set(LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY ON) endif() -if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) +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") @@ -259,14 +259,14 @@ if (LIBCXX_ENABLE_STATIC) list(APPEND LIBCXX_TARGETS "cxx_static") # Attempt to merge the libc++.a archive and the ABI library archive into one. - if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) + if (LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY) set(MERGE_ARCHIVES_SEARCH_PATHS "") if (LIBCXX_CXX_ABI_LIBRARY_PATH) set(MERGE_ARCHIVES_SEARCH_PATHS "-L${LIBCXX_CXX_ABI_LIBRARY_PATH}") endif() if ((TARGET ${LIBCXX_CXX_ABI_LIBRARY}) OR (${LIBCXX_CXX_ABI_LIBRARY} MATCHES "cxxabi(_static|_shared)?" AND HAVE_LIBCXXABI)) - set(MERGE_ARCHIVES_ABI_TARGET "$") + set(MERGE_ARCHIVES_ABI_TARGET "$") else() set(MERGE_ARCHIVES_ABI_TARGET "${CMAKE_STATIC_LIBRARY_PREFIX}${LIBCXX_CXX_ABI_LIBRARY}${CMAKE_STATIC_LIBRARY_SUFFIX}") -- GitLab From 04ce4aef00d3ee508327f6cf7bf1b1d200ab6238 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 23 Jul 2018 04:55:57 +0000 Subject: [PATCH 052/495] Use possibly cached directory entry values when performing recursive directory iteration. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337669 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/directory_iterator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/experimental/filesystem/directory_iterator.cpp b/src/experimental/filesystem/directory_iterator.cpp index 60f234cb1..b49ea398f 100644 --- a/src/experimental/filesystem/directory_iterator.cpp +++ b/src/experimental/filesystem/directory_iterator.cpp @@ -359,13 +359,13 @@ bool recursive_directory_iterator::__try_recursion(error_code *ec) { bool skip_rec = false; std::error_code m_ec; if (!rec_sym) { - file_status st = curr_it.__entry_.symlink_status(m_ec); + file_status st(curr_it.__entry_.__get_sym_ft(&m_ec)); if (m_ec && status_known(st)) m_ec.clear(); if (m_ec || is_symlink(st) || !is_directory(st)) skip_rec = true; } else { - file_status st = curr_it.__entry_.status(m_ec); + file_status st(curr_it.__entry_.__get_ft(&m_ec)); if (m_ec && status_known(st)) m_ec.clear(); if (m_ec || !is_directory(st)) -- GitLab From 78c3548b8810169f83451551491d8c18f96558ca Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Mon, 23 Jul 2018 05:07:44 +0000 Subject: [PATCH 053/495] Revert "[CMake] Support statically linking dependencies only to shared or static library" This reverts commit r337668: broke the cxxabi build when using Make. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337670 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 8 -------- cmake/Modules/HandleLibCXXABI.cmake | 6 +++--- lib/CMakeLists.txt | 6 +++--- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df59b5610..6521ebbe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,14 +155,6 @@ endif() # cannot be used with LIBCXX_ENABLE_ABI_LINKER_SCRIPT. option(LIBCXX_ENABLE_STATIC_ABI_LIBRARY "Statically link the ABI library" OFF) -cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY - "Statically link the ABI library to static library" ON - "LIBCXX_ENABLE_STATIC_ABI_LIBRARY;LIBCXX_ENABLE_STATIC" OFF) - -cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY - "Statically link the ABI library to shared library" ON - "LIBCXX_ENABLE_STATIC_ABI_LIBRARY;LIBCXX_ENABLE_STATIC" OFF) - # Generate and install a linker script inplace of libc++.so. The linker script # will link libc++ to the correct ABI library. This option is on by default # on UNIX platforms other than Apple unless 'LIBCXX_ENABLE_STATIC_ABI_LIBRARY' diff --git a/cmake/Modules/HandleLibCXXABI.cmake b/cmake/Modules/HandleLibCXXABI.cmake index d837c3c37..0eb70a739 100644 --- a/cmake/Modules/HandleLibCXXABI.cmake +++ b/cmake/Modules/HandleLibCXXABI.cmake @@ -96,10 +96,10 @@ if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++" OR elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi") if (LIBCXX_CXX_ABI_INTREE) # Link against just-built "cxxabi" target. - if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY) - set(CXXABI_LIBNAME cxxabi_static) + if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) + set(CXXABI_LIBNAME cxxabi_static) else() - set(CXXABI_LIBNAME cxxabi_shared) + set(CXXABI_LIBNAME cxxabi_shared) endif() set(LIBCXX_LIBCPPABI_VERSION "2" PARENT_SCOPE) else() diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 5ac691a75..d32f8fb8e 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -44,7 +44,7 @@ if (APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR set(LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY ON) endif() -if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY) +if (LIBCXX_ENABLE_STATIC_ABI_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") @@ -259,14 +259,14 @@ if (LIBCXX_ENABLE_STATIC) list(APPEND LIBCXX_TARGETS "cxx_static") # Attempt to merge the libc++.a archive and the ABI library archive into one. - if (LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY) + if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) set(MERGE_ARCHIVES_SEARCH_PATHS "") if (LIBCXX_CXX_ABI_LIBRARY_PATH) set(MERGE_ARCHIVES_SEARCH_PATHS "-L${LIBCXX_CXX_ABI_LIBRARY_PATH}") endif() if ((TARGET ${LIBCXX_CXX_ABI_LIBRARY}) OR (${LIBCXX_CXX_ABI_LIBRARY} MATCHES "cxxabi(_static|_shared)?" AND HAVE_LIBCXXABI)) - set(MERGE_ARCHIVES_ABI_TARGET "$") + set(MERGE_ARCHIVES_ABI_TARGET "$") else() set(MERGE_ARCHIVES_ABI_TARGET "${CMAKE_STATIC_LIBRARY_PREFIX}${LIBCXX_CXX_ABI_LIBRARY}${CMAKE_STATIC_LIBRARY_SUFFIX}") -- GitLab From 68265538036847cd4c50a9d45ad9abfc5fb409b4 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 23 Jul 2018 11:46:47 +0000 Subject: [PATCH 054/495] Cleanup name qualification in the filesystem internals. In most cases there is no reason why the filesystem internals use the qualifier std:: or _VSTD::. This patch removes the unneeded qualifiers, making the sources files more consistent git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337684 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../filesystem/directory_iterator.cpp | 44 ++--- .../filesystem/filesystem_common.h | 26 +-- src/experimental/filesystem/operations.cpp | 166 +++++++++--------- 3 files changed, 118 insertions(+), 118 deletions(-) diff --git a/src/experimental/filesystem/directory_iterator.cpp b/src/experimental/filesystem/directory_iterator.cpp index b49ea398f..7b485b4c6 100644 --- a/src/experimental/filesystem/directory_iterator.cpp +++ b/src/experimental/filesystem/directory_iterator.cpp @@ -98,8 +98,8 @@ public: __dir_stream& operator=(const __dir_stream&) = delete; __dir_stream(__dir_stream&& __ds) noexcept - : __stream_(__ds.__stream_), __root_(std::move(__ds.__root_)), - __entry_(std::move(__ds.__entry_)) { + : __stream_(__ds.__stream_), __root_(move(__ds.__root_)), + __entry_(move(__ds.__entry_)) { __ds.__stream_ = INVALID_HANDLE_VALUE; } @@ -107,7 +107,7 @@ public: : __stream_(INVALID_HANDLE_VALUE), __root_(root) { __stream_ = ::FindFirstFileEx(root.c_str(), &__data_); if (__stream_ == INVALID_HANDLE_VALUE) { - ec = error_code(::GetLastError(), std::generic_category()); + ec = error_code(::GetLastError(), generic_category()); const bool ignore_permission_denied = bool(opts & directory_options::skip_permission_denied); if (ignore_permission_denied && ec.value() == ERROR_ACCESS_DENIED) @@ -138,16 +138,16 @@ public: directory_entry::__create_iter_result(get_file_type(__data))); return true; } - ec = error_code(::GetLastError(), std::generic_category()); + ec = error_code(::GetLastError(), generic_category()); close(); return false; } private: - std::error_code close() noexcept { - std::error_code ec; + error_code close() noexcept { + error_code ec; if (!::FindClose(__stream_)) - ec = error_code(::GetLastError(), std::generic_category()); + ec = error_code(::GetLastError(), generic_category()); __stream_ = INVALID_HANDLE_VALUE; return ec; } @@ -166,8 +166,8 @@ public: __dir_stream& operator=(const __dir_stream&) = delete; __dir_stream(__dir_stream&& other) noexcept - : __stream_(other.__stream_), __root_(std::move(other.__root_)), - __entry_(std::move(other.__entry_)) + : __stream_(other.__stream_), __root_(move(other.__root_)), + __entry_(move(other.__entry_)) { other.__stream_ = nullptr; } @@ -211,8 +211,8 @@ public: } } private: - std::error_code close() noexcept { - std::error_code m_ec; + error_code close() noexcept { + error_code m_ec; if (::closedir(__stream_) == -1) m_ec = detail::capture_errno(); __stream_ = nullptr; @@ -233,7 +233,7 @@ directory_iterator::directory_iterator(const path& p, error_code *ec, { ErrorHandler err("directory_iterator::directory_iterator(...)", ec, &p); - std::error_code m_ec; + error_code m_ec; __imp_ = make_shared<__dir_stream>(p, opts, m_ec); if (ec) *ec = m_ec; @@ -249,9 +249,9 @@ directory_iterator& directory_iterator::__increment(error_code *ec) _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator"); ErrorHandler err("directory_iterator::operator++()", ec); - std::error_code m_ec; + error_code m_ec; if (!__imp_->advance(m_ec)) { - path root = std::move(__imp_->__root_); + path root = move(__imp_->__root_); __imp_.reset(); if (m_ec) err.report(m_ec, "at root \"%s\"", root); @@ -278,16 +278,16 @@ recursive_directory_iterator::recursive_directory_iterator(const path& p, { ErrorHandler err("recursive_directory_iterator", ec, &p); - std::error_code m_ec; + error_code m_ec; __dir_stream new_s(p, opt, m_ec); if (m_ec) err.report(m_ec); if (m_ec || !new_s.good()) return; - __imp_ = _VSTD::make_shared<__shared_imp>(); + __imp_ = make_shared<__shared_imp>(); __imp_->__options_ = opt; - __imp_->__stack_.push(_VSTD::move(new_s)); + __imp_->__stack_.push(move(new_s)); } void recursive_directory_iterator::__pop(error_code* ec) @@ -331,7 +331,7 @@ void recursive_directory_iterator::__advance(error_code* ec) { const directory_iterator end_it; auto& stack = __imp_->__stack_; - std::error_code m_ec; + error_code m_ec; while (stack.size() > 0) { if (stack.top().advance(m_ec)) return; @@ -341,7 +341,7 @@ void recursive_directory_iterator::__advance(error_code* ec) { } if (m_ec) { - path root = std::move(stack.top().__root_); + path root = move(stack.top().__root_); __imp_.reset(); err.report(m_ec, "at root \"%s\"", root); } else { @@ -357,7 +357,7 @@ bool recursive_directory_iterator::__try_recursion(error_code *ec) { auto& curr_it = __imp_->__stack_.top(); bool skip_rec = false; - std::error_code m_ec; + error_code m_ec; if (!rec_sym) { file_status st(curr_it.__entry_.__get_sym_ft(&m_ec)); if (m_ec && status_known(st)) @@ -375,7 +375,7 @@ bool recursive_directory_iterator::__try_recursion(error_code *ec) { if (!skip_rec) { __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec); if (new_it.good()) { - __imp_->__stack_.push(_VSTD::move(new_it)); + __imp_->__stack_.push(move(new_it)); return true; } } @@ -385,7 +385,7 @@ bool recursive_directory_iterator::__try_recursion(error_code *ec) { if (m_ec.value() == EACCES && allow_eacess) { if (ec) ec->clear(); } else { - path at_ent = std::move(curr_it.__entry_.__p_); + path at_ent = move(curr_it.__entry_.__p_); __imp_.reset(); err.report(m_ec, "attempting recursion into \"%s\"", at_ent); } diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index 6db0cac7f..22ad9c313 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -67,7 +67,7 @@ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM namespace detail { namespace { -static std::string format_string_imp(const char* msg, ...) { +static string format_string_imp(const char* msg, ...) { // we might need a second shot at this, so pre-emptivly make a copy struct GuardVAList { va_list& target; @@ -91,24 +91,24 @@ static std::string format_string_imp(const char* msg, ...) { va_copy(args_cp, args); GuardVAList args_copy_guard(args_cp); - std::array local_buff; - std::size_t size = local_buff.size(); + array local_buff; + size_t size = local_buff.size(); auto ret = ::vsnprintf(local_buff.data(), size, msg, args_cp); args_copy_guard.clear(); // handle empty expansion if (ret == 0) - return std::string{}; - if (static_cast(ret) < size) - return std::string(local_buff.data()); + return string{}; + if (static_cast(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(ret) + 1; - auto buff_ptr = std::unique_ptr(new char[size]); + size = static_cast(ret) + 1; + auto buff_ptr = unique_ptr(new char[size]); ret = ::vsnprintf(buff_ptr.get(), size, msg, args); - return std::string(buff_ptr.get()); + return string(buff_ptr.get()); } const char* unwrap(string const& s) { return s.c_str(); } @@ -120,13 +120,13 @@ Arg const& unwrap(Arg const& a) { } template -std::string format_string(const char* fmt, Args const&... args) { +string format_string(const char* fmt, Args const&... args) { return format_string_imp(fmt, unwrap(args)...); } -std::error_code capture_errno() { +error_code capture_errno() { _LIBCPP_ASSERT(errno, "Expected errno to be non-zero"); - return std::error_code(errno, std::generic_category()); + return error_code(errno, generic_category()); } template @@ -375,7 +375,7 @@ using TimeStructArray = TimeStruct[2]; #endif bool SetFileTimes(const path& p, TimeStructArray const& TS, - std::error_code& ec) { + error_code& ec) { #if !defined(_LIBCXX_USE_UTIMENSAT) if (::utimes(p.c_str(), TS) == -1) #else diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index a3dd4349d..33583f45f 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -330,7 +330,7 @@ struct FileDescriptor { bool status_known() const { return _VSTD_FS::status_known(m_status); } - file_status refresh_status(std::error_code& ec); + file_status refresh_status(error_code& ec); void close() noexcept { if (fd != -1) @@ -363,9 +363,9 @@ perms posix_get_perms(const struct ::stat& st) noexcept { return static_cast< ::mode_t>(prms & perms::mask); } -file_status create_file_status(std::error_code& m_ec, path const& p, +file_status create_file_status(error_code& m_ec, path const& p, const struct ::stat& path_stat, - std::error_code* ec) { + error_code* ec) { if (ec) *ec = m_ec; if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { @@ -401,33 +401,33 @@ file_status create_file_status(std::error_code& m_ec, path const& p, } file_status posix_stat(path const& p, struct ::stat& path_stat, - std::error_code* ec) { - std::error_code m_ec; + error_code* ec) { + error_code m_ec; if (::stat(p.c_str(), &path_stat) == -1) m_ec = detail::capture_errno(); return create_file_status(m_ec, p, path_stat, ec); } -file_status posix_stat(path const& p, std::error_code* ec) { +file_status posix_stat(path const& p, error_code* ec) { struct ::stat path_stat; return posix_stat(p, path_stat, ec); } file_status posix_lstat(path const& p, struct ::stat& path_stat, - std::error_code* ec) { - std::error_code m_ec; + error_code* ec) { + error_code m_ec; if (::lstat(p.c_str(), &path_stat) == -1) m_ec = detail::capture_errno(); return create_file_status(m_ec, p, path_stat, ec); } -file_status posix_lstat(path const& p, std::error_code* ec) { +file_status posix_lstat(path const& p, error_code* ec) { struct ::stat path_stat; return posix_lstat(p, path_stat, ec); } bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, - std::error_code& ec) { + error_code& ec) { if (::ftruncate(fd.fd, to_size) == -1) { ec = capture_errno(); return false; @@ -449,11 +449,11 @@ bool stat_equivalent(const StatT& st1, const StatT& st2) { return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino); } -file_status FileDescriptor::refresh_status(std::error_code& ec) { +file_status FileDescriptor::refresh_status(error_code& ec) { // FD must be open and good. m_status = file_status{}; m_stat = {}; - std::error_code m_ec; + error_code m_ec; if (::fstat(fd, &m_stat) == -1) m_ec = capture_errno(); m_status = create_file_status(m_ec, name, m_stat, &ec); @@ -486,7 +486,7 @@ void filesystem_error::__create_what(int __num_paths) { }(); } -static path __do_absolute(const path& p, path *cwd, std::error_code *ec) { +static path __do_absolute(const path& p, path *cwd, error_code *ec) { if (ec) ec->clear(); if (p.is_absolute()) return p; @@ -496,12 +496,12 @@ static path __do_absolute(const path& p, path *cwd, std::error_code *ec) { return (*cwd) / p; } -path __absolute(const path& p, std::error_code *ec) { +path __absolute(const path& p, error_code *ec) { path cwd; return __do_absolute(p, &cwd, ec); } -path __canonical(path const & orig_p, std::error_code *ec) +path __canonical(path const & orig_p, error_code *ec) { path cwd; ErrorHandler err("canonical", ec, &orig_p, &cwd); @@ -515,7 +515,7 @@ path __canonical(path const & orig_p, std::error_code *ec) } void __copy(const path& from, const path& to, copy_options options, - std::error_code *ec) + error_code *ec) { ErrorHandler err("copy", ec, &from, &to); @@ -524,7 +524,7 @@ void __copy(const path& from, const path& to, copy_options options, const bool sym_status2 = bool(options & copy_options::copy_symlinks); - std::error_code m_ec1; + error_code m_ec1; struct ::stat f_st = {}; const file_status f = sym_status || sym_status2 ? detail::posix_lstat(from, f_st, &m_ec1) @@ -588,7 +588,7 @@ void __copy(const path& from, const path& to, copy_options options, directory_iterator it = ec ? directory_iterator(from, *ec) : directory_iterator(from); if (ec && *ec) { return; } - std::error_code m_ec2; + error_code m_ec2; for (; it != directory_iterator(); it.increment(m_ec2)) { if (m_ec2) { return err.report(m_ec2); @@ -651,27 +651,27 @@ bool copy_file_impl_copyfile(FileDescriptor& read_fd, FileDescriptor& write_fd, __attribute__((unused)) bool copy_file_impl_default(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { - std::ifstream in; - in.__open(read_fd.fd, std::ios::binary); + ifstream in; + in.__open(read_fd.fd, ios::binary); if (!in.is_open()) { // This assumes that __open didn't reset the error code. ec = capture_errno(); return false; } - std::ofstream out; - out.__open(write_fd.fd, std::ios::binary); + ofstream out; + out.__open(write_fd.fd, ios::binary); if (!out.is_open()) { ec = capture_errno(); return false; } if (in.good() && out.good()) { - using InIt = std::istreambuf_iterator; - using OutIt = std::ostreambuf_iterator; + using InIt = istreambuf_iterator; + using OutIt = ostreambuf_iterator; InIt bin(in); InIt ein; OutIt bout(out); - std::copy(bin, ein, bout); + copy(bin, ein, bout); } if (out.fail() || in.fail()) { ec = make_error_code(errc::io_error); @@ -696,12 +696,12 @@ bool copy_file_impl(FileDescriptor& from, FileDescriptor& to, error_code& ec) { } // namespace detail bool __copy_file(const path& from, const path& to, copy_options options, - std::error_code *ec) + error_code *ec) { using detail::FileDescriptor; ErrorHandler err("copy_file", ec, &to, &from); - std::error_code m_ec; + error_code m_ec; FileDescriptor from_fd = FileDescriptor::create_with_status(&from, m_ec, O_RDONLY | O_NONBLOCK); if (m_ec) @@ -786,7 +786,7 @@ bool __copy_file(const path& from, const path& to, copy_options options, } void __copy_symlink(const path& existing_symlink, const path& new_symlink, - std::error_code *ec) + error_code *ec) { const path real_path(__read_symlink(existing_symlink, ec)); if (ec && *ec) { return; } @@ -796,11 +796,11 @@ void __copy_symlink(const path& existing_symlink, const path& new_symlink, __create_symlink(real_path, new_symlink, ec); } -bool __create_directories(const path& p, std::error_code *ec) +bool __create_directories(const path& p, error_code *ec) { ErrorHandler err("create_directories", ec, &p); - std::error_code m_ec; + error_code m_ec; auto const st = detail::posix_stat(p, &m_ec); if (!status_known(st)) return err.report(m_ec); @@ -824,7 +824,7 @@ bool __create_directories(const path& p, std::error_code *ec) return __create_directory(p, ec); } -bool __create_directory(const path& p, std::error_code *ec) +bool __create_directory(const path& p, error_code *ec) { ErrorHandler err("create_directory", ec, &p); @@ -836,12 +836,12 @@ bool __create_directory(const path& p, std::error_code *ec) } bool __create_directory(path const & p, path const & attributes, - std::error_code *ec) + error_code *ec) { ErrorHandler err("create_directory", ec, &p, &attributes); StatT attr_stat; - std::error_code mec; + error_code mec; auto st = detail::posix_stat(attributes, attr_stat, &mec); if (!status_known(st)) return err.report(mec); @@ -854,31 +854,31 @@ bool __create_directory(path const & p, path const & attributes, } void __create_directory_symlink(path const& from, path const& to, - std::error_code* ec) { + error_code* ec) { ErrorHandler err("create_directory_symlink", ec, &from, &to); if (::symlink(from.c_str(), to.c_str()) != 0) return err.report(capture_errno()); } -void __create_hard_link(const path& from, const path& to, std::error_code *ec){ +void __create_hard_link(const path& from, const path& to, error_code *ec){ ErrorHandler err("create_hard_link", ec, &from, &to); if (::link(from.c_str(), to.c_str()) == -1) return err.report(capture_errno()); } -void __create_symlink(path const & from, path const & to, std::error_code *ec) { +void __create_symlink(path const & from, path const & to, error_code *ec) { ErrorHandler err("create_symlink", ec, &from, &to); if (::symlink(from.c_str(), to.c_str()) == -1) return err.report(capture_errno()); } -path __current_path(std::error_code *ec) { +path __current_path(error_code *ec) { ErrorHandler err("current_path", ec); auto size = ::pathconf(".", _PC_PATH_MAX); _LIBCPP_ASSERT(size >= 0, "pathconf returned a 0 as max size"); - auto buff = std::unique_ptr(new char[size + 1]); + auto buff = unique_ptr(new char[size + 1]); char* ret; if ((ret = ::getcwd(buff.get(), static_cast(size))) == nullptr) return err.report(capture_errno(), "call to getcwd failed"); @@ -886,17 +886,17 @@ path __current_path(std::error_code *ec) { return {buff.get()}; } -void __current_path(const path& p, std::error_code *ec) { +void __current_path(const path& p, error_code *ec) { ErrorHandler err("current_path", ec, &p); if (::chdir(p.c_str()) == -1) err.report(capture_errno()); } -bool __equivalent(const path& p1, const path& p2, std::error_code *ec) +bool __equivalent(const path& p1, const path& p2, error_code *ec) { ErrorHandler err("equivalent", ec, &p1, &p2); - std::error_code ec1, ec2; + error_code ec1, ec2; StatT st1 = {}, st2 = {}; auto s1 = detail::posix_stat(p1.native(), st1, &ec1); if (!exists(s1)) @@ -909,11 +909,11 @@ bool __equivalent(const path& p1, const path& p2, std::error_code *ec) } -std::uintmax_t __file_size(const path& p, std::error_code *ec) +uintmax_t __file_size(const path& p, error_code *ec) { ErrorHandler err("file_size", ec, &p); - std::error_code m_ec; + error_code m_ec; struct ::stat st; file_status fst = detail::posix_stat(p, st, &m_ec); if (!exists(fst) || !is_regular_file(fst)) { @@ -924,27 +924,27 @@ std::uintmax_t __file_size(const path& p, std::error_code *ec) return err.report(m_ec); } // is_regular_file(p) == true - return static_cast(st.st_size); + return static_cast(st.st_size); } -std::uintmax_t __hard_link_count(const path& p, std::error_code *ec) +uintmax_t __hard_link_count(const path& p, error_code *ec) { ErrorHandler err("hard_link_count", ec, &p); - std::error_code m_ec; + error_code m_ec; StatT st; detail::posix_stat(p, st, &m_ec); if (m_ec) return err.report(m_ec); - return static_cast(st.st_nlink); + return static_cast(st.st_nlink); } -bool __fs_is_empty(const path& p, std::error_code *ec) +bool __fs_is_empty(const path& p, error_code *ec) { ErrorHandler err("is_empty", ec, &p); - std::error_code m_ec; + error_code m_ec; StatT pst; auto st = detail::posix_stat(p, pst, &m_ec); if (m_ec) @@ -957,7 +957,7 @@ bool __fs_is_empty(const path& p, std::error_code *ec) return false; return it == directory_iterator{}; } else if (is_regular_file(st)) - return static_cast(pst.st_size) == 0; + return static_cast(pst.st_size) == 0; _LIBCPP_UNREACHABLE(); } @@ -974,12 +974,12 @@ static file_time_type __extract_last_write_time(const path& p, const StatT& st, return FSTime::convert_timespec(ts); } -file_time_type __last_write_time(const path& p, std::error_code *ec) +file_time_type __last_write_time(const path& p, error_code *ec) { - using namespace ::std::chrono; + using namespace chrono; ErrorHandler err("last_write_time", ec, &p); - std::error_code m_ec; + error_code m_ec; StatT st; detail::posix_stat(p, st, &m_ec); if (m_ec) @@ -988,14 +988,14 @@ file_time_type __last_write_time(const path& p, std::error_code *ec) } void __last_write_time(const path& p, file_time_type new_time, - std::error_code *ec) + error_code *ec) { - using namespace std::chrono; + using namespace chrono; using namespace detail; ErrorHandler err("last_write_time", ec, &p); - std::error_code m_ec; + error_code m_ec; TimeStructArray tbuf; #if !defined(_LIBCXX_USE_UTIMENSAT) // This implementation has a race condition between determining the @@ -1020,7 +1020,7 @@ void __last_write_time(const path& p, file_time_type new_time, void __permissions(const path& p, perms prms, perm_options opts, - std::error_code *ec) + error_code *ec) { ErrorHandler err("permissions", ec, &p); @@ -1036,7 +1036,7 @@ void __permissions(const path& p, perms prms, perm_options opts, bool set_sym_perms = false; prms &= perms::mask; if (!resolve_symlinks || (add_perms || remove_perms)) { - std::error_code m_ec; + error_code m_ec; file_status st = resolve_symlinks ? detail::posix_stat(p, &m_ec) : detail::posix_lstat(p, &m_ec); set_sym_perms = is_symlink(st); @@ -1066,11 +1066,11 @@ void __permissions(const path& p, perms prms, perm_options opts, } -path __read_symlink(const path& p, std::error_code *ec) { +path __read_symlink(const path& p, error_code *ec) { ErrorHandler err("read_symlink", ec, &p); char buff[PATH_MAX + 1]; - std::error_code m_ec; + error_code m_ec; ::ssize_t ret; if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) { return err.report(capture_errno()); @@ -1082,7 +1082,7 @@ path __read_symlink(const path& p, std::error_code *ec) { } -bool __remove(const path& p, std::error_code *ec) { +bool __remove(const path& p, error_code *ec) { ErrorHandler err("remove", ec, &p); if (::remove(p.c_str()) == -1) { if (errno != ENOENT) @@ -1094,12 +1094,12 @@ bool __remove(const path& p, std::error_code *ec) { namespace { -std::uintmax_t remove_all_impl(path const & p, std::error_code& ec) +uintmax_t remove_all_impl(path const & p, error_code& ec) { - const auto npos = static_cast(-1); + const auto npos = static_cast(-1); const file_status st = __symlink_status(p, &ec); if (ec) return npos; - std::uintmax_t count = 1; + uintmax_t count = 1; if (is_directory(st)) { for (directory_iterator it(p, ec); !ec && it != directory_iterator(); it.increment(ec)) { @@ -1115,10 +1115,10 @@ std::uintmax_t remove_all_impl(path const & p, std::error_code& ec) } // end namespace -std::uintmax_t __remove_all(const path& p, std::error_code *ec) { +uintmax_t __remove_all(const path& p, error_code *ec) { ErrorHandler err("remove_all", ec, &p); - std::error_code mec; + error_code mec; auto count = remove_all_impl(p, mec); if (mec) { if (mec == errc::no_such_file_or_directory) @@ -1128,32 +1128,32 @@ std::uintmax_t __remove_all(const path& p, std::error_code *ec) { return count; } -void __rename(const path& from, const path& to, std::error_code *ec) { +void __rename(const path& from, const path& to, error_code *ec) { ErrorHandler err("rename", ec, &from, &to); if (::rename(from.c_str(), to.c_str()) == -1) err.report(capture_errno()); } -void __resize_file(const path& p, std::uintmax_t size, std::error_code *ec) { +void __resize_file(const path& p, uintmax_t size, error_code *ec) { ErrorHandler err("resize_file", ec, &p); if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) return err.report(capture_errno()); } -space_info __space(const path& p, std::error_code *ec) { +space_info __space(const path& p, error_code *ec) { ErrorHandler err("space", ec, &p); space_info si; struct statvfs m_svfs = {}; if (::statvfs(p.c_str(), &m_svfs) == -1) { err.report(capture_errno()); - si.capacity = si.free = si.available = static_cast(-1); + si.capacity = si.free = si.available = static_cast(-1); return si; } // Multiply with overflow checking. - auto do_mult = [&](std::uintmax_t& out, std::uintmax_t other) { + auto do_mult = [&](uintmax_t& out, uintmax_t other) { out = other * m_svfs.f_frsize; if (other == 0 || out / other != m_svfs.f_frsize) - out = static_cast(-1); + out = static_cast(-1); }; do_mult(si.capacity, m_svfs.f_blocks); do_mult(si.free, m_svfs.f_bfree); @@ -1161,28 +1161,28 @@ space_info __space(const path& p, std::error_code *ec) { return si; } -file_status __status(const path& p, std::error_code *ec) { +file_status __status(const path& p, error_code *ec) { return detail::posix_stat(p, ec); } -file_status __symlink_status(const path& p, std::error_code *ec) { +file_status __symlink_status(const path& p, error_code *ec) { return detail::posix_lstat(p, ec); } -path __temp_directory_path(std::error_code* ec) { +path __temp_directory_path(error_code* ec) { ErrorHandler err("temp_directory_path", ec); const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; const char* ret = nullptr; for (auto& ep : env_paths) - if ((ret = std::getenv(ep))) + if ((ret = getenv(ep))) break; if (ret == nullptr) ret = "/tmp"; path p(ret); - std::error_code m_ec; + error_code m_ec; file_status st = detail::posix_stat(p, &m_ec); if (!status_known(st)) return err.report(m_ec, "cannot access path \"%s\"", p); @@ -1195,7 +1195,7 @@ path __temp_directory_path(std::error_code* ec) { } -path __weakly_canonical(const path& p, std::error_code *ec) { +path __weakly_canonical(const path& p, error_code *ec) { ErrorHandler err("weakly_canonical", ec, &p); if (p.empty()) @@ -1206,11 +1206,11 @@ path __weakly_canonical(const path& p, std::error_code *ec) { tmp.__reserve(p.native().size()); auto PP = PathParser::CreateEnd(p.native()); --PP; - std::vector DNEParts; + vector DNEParts; while (PP.State != PathParser::PS_BeforeBegin) { tmp.assign(createView(p.native().data(), &PP.RawEntry.back())); - std::error_code m_ec; + error_code m_ec; file_status st = __status(tmp, &m_ec); if (!status_known(st)) { return err.report(m_ec); @@ -1376,8 +1376,8 @@ path path::lexically_normal() const { if (__pn_.empty()) return *this; - using PartKindPair = std::pair; - std::vector Parts; + using PartKindPair = pair; + vector Parts; // Guess as to how many elements the path has to avoid reallocating. Parts.reserve(32); @@ -1533,7 +1533,7 @@ int path::__compare(string_view_t __s) const { size_t hash_value(const path& __p) noexcept { auto PP = PathParser::CreateBegin(__p.native()); size_t hash_value = 0; - std::hash hasher; + hash hasher; while (PP) { hash_value = __hash_combine(hash_value, hasher(*PP)); ++PP; -- GitLab From 36bf18fc64b531fd994000cee56ff7c7d2181d13 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 23 Jul 2018 11:55:13 +0000 Subject: [PATCH 055/495] Cleanup unnecessary conversions in filesystem. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337685 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/operations.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index 33583f45f..dd805193b 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -727,10 +727,10 @@ bool __copy_file(const path& from, const path& to, copy_options options, const bool to_exists = exists(to_st); if (to_exists && !is_regular_file(to_st)) - return err.report(make_error_code(errc::not_supported)); + return err.report(errc::not_supported); if (to_exists && detail::stat_equivalent(from_stat, to_stat_path)) - return err.report(make_error_code(errc::file_exists)); + return err.report(errc::file_exists); if (to_exists && skip_existing) return false; -- GitLab From 80412b50ea558a47da9a81fa8a9b14244aba4c85 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Mon, 23 Jul 2018 18:58:12 +0000 Subject: [PATCH 056/495] [CMake] Fix the setting of LIBCXX_HEADER_DIR Reviewers: phosek Subscribers: mgorny, christof, ldionne, cfe-commits Differential Revision: https://reviews.llvm.org/D49629 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337727 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6521ebbe4..28e2eb749 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -378,7 +378,7 @@ endif () set(LIBCXX_COMPILER ${CMAKE_CXX_COMPILER}) set(LIBCXX_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(LIBCXX_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) -set(LIBCXX_HEADER_DIR ${LLVM_BINARY_DIR}) +set(LIBCXX_HEADER_DIR ${LIBCXX_BINARY_DIR}) set(LIBCXX_BINARY_INCLUDE_DIR "${LIBCXX_BINARY_DIR}/include/c++build") string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION -- GitLab From 7485d577aa5ffdf001134a3d13b7fb7a4e7ed3ea Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 23 Jul 2018 21:52:29 +0000 Subject: [PATCH 057/495] Revert "Use possibly cached directory entry values when performing recursive directory iteration." This reverts commit 04ce4aef00d3ee508327f6cf7bf1b1d200ab6238. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337749 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/directory_iterator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/experimental/filesystem/directory_iterator.cpp b/src/experimental/filesystem/directory_iterator.cpp index 7b485b4c6..a6f10d075 100644 --- a/src/experimental/filesystem/directory_iterator.cpp +++ b/src/experimental/filesystem/directory_iterator.cpp @@ -359,13 +359,13 @@ bool recursive_directory_iterator::__try_recursion(error_code *ec) { bool skip_rec = false; error_code m_ec; if (!rec_sym) { - file_status st(curr_it.__entry_.__get_sym_ft(&m_ec)); + file_status st = curr_it.__entry_.symlink_status(m_ec); if (m_ec && status_known(st)) m_ec.clear(); if (m_ec || is_symlink(st) || !is_directory(st)) skip_rec = true; } else { - file_status st(curr_it.__entry_.__get_ft(&m_ec)); + file_status st = curr_it.__entry_.status(m_ec); if (m_ec && status_known(st)) m_ec.clear(); if (m_ec || !is_directory(st)) -- GitLab From f581ed2017837189e263114a75dac53b56465d84 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 23 Jul 2018 22:39:56 +0000 Subject: [PATCH 058/495] Fix accidentally removed test. When adding the new tests for the filesystem_error::what method, I incorrectly removed a test case and replaced it with something else. This patch restores that test case git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337764 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../rec.dir.itr.members/increment.pass.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp b/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp index 830f4a943..ad6151881 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp +++ b/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp @@ -25,8 +25,6 @@ #include "rapid-cxx-test.hpp" #include "filesystem_test_helper.hpp" -#include - using namespace fs; TEST_SUITE(recursive_directory_iterator_increment_tests) @@ -290,6 +288,21 @@ TEST_CASE(test_PR35078) TEST_CHECK(ec == eacess_ec); TEST_CHECK(it == endIt); } + { + bool SeenNestedFile = false; + recursive_directory_iterator it = SetupState(true, SeenNestedFile); + TEST_REQUIRE(it != endIt); + TEST_REQUIRE(*it == nestedDir); + ec = GetTestEC(); + it.increment(ec); + TEST_CHECK(!ec); + if (SeenNestedFile) { + TEST_CHECK(it == endIt); + } else { + TEST_REQUIRE(it != endIt); + TEST_CHECK(*it == nestedFile); + } + } { bool SeenNestedFile = false; recursive_directory_iterator it = SetupState(false, SeenNestedFile); -- GitLab From 2c1163593fc761e13e886b270809964aec21f035 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 23 Jul 2018 22:40:41 +0000 Subject: [PATCH 059/495] Recommit "Use possibly cached directory entry values when performing recursive directory iteration." The initial patch didn't correctly handle systems when the dirent struct didn't provide the d_type member. Specifically it set the cache to the incorrect state, and claimed it was partially populated. The updated version of this change correctly handles setting up the cache when the file type is not known (aka file_type::none). git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337765 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/experimental/filesystem | 12 ++++++++++-- src/experimental/filesystem/directory_iterator.cpp | 7 ++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/experimental/filesystem b/include/experimental/filesystem index 2ed3eecff..9699699c7 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -2200,8 +2200,16 @@ private: static __cached_data __create_iter_result(file_type __ft) { __cached_data __data; __data.__type_ = __ft; - __data.__cache_type_ = - __ft == file_type::symlink ? _IterSymlink : _IterNonSymlink; + __data.__cache_type_ = [&]() { + switch (__ft) { + case file_type::none: + return _Empty; + case file_type::symlink: + return _IterSymlink; + default: + return _IterNonSymlink; + } + }(); return __data; } diff --git a/src/experimental/filesystem/directory_iterator.cpp b/src/experimental/filesystem/directory_iterator.cpp index a6f10d075..c95ebc8ac 100644 --- a/src/experimental/filesystem/directory_iterator.cpp +++ b/src/experimental/filesystem/directory_iterator.cpp @@ -47,9 +47,10 @@ static file_type get_file_type(DirEntT *ent, int) { } return file_type::none; } + template static file_type get_file_type(DirEntT *ent, long) { - return file_type::unknown; + return file_type::none; } static pair @@ -359,13 +360,13 @@ bool recursive_directory_iterator::__try_recursion(error_code *ec) { bool skip_rec = false; error_code m_ec; if (!rec_sym) { - file_status st = curr_it.__entry_.symlink_status(m_ec); + file_status st(curr_it.__entry_.__get_sym_ft(&m_ec)); if (m_ec && status_known(st)) m_ec.clear(); if (m_ec || is_symlink(st) || !is_directory(st)) skip_rec = true; } else { - file_status st = curr_it.__entry_.status(m_ec); + file_status st(curr_it.__entry_.__get_ft(&m_ec)); if (m_ec && status_known(st)) m_ec.clear(); if (m_ec || !is_directory(st)) -- GitLab From b3e55b246d16e2a9f0ea67a814c1e3566a8e36ab Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Mon, 23 Jul 2018 22:58:46 +0000 Subject: [PATCH 060/495] Handle DT_UNKNOWN correctly during directory iteration. Unlike stat and lstat, where unknown really means we know it's something weird, during directory iteration DT_UNKNOWN simply means that the underlying FS doesn't support the dirent::dt_type field. This patch fixes libc++ to correctly set the cache to empty when DT_UNKNOWN is reported. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337768 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/directory_iterator.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/experimental/filesystem/directory_iterator.cpp b/src/experimental/filesystem/directory_iterator.cpp index c95ebc8ac..7a1ab2573 100644 --- a/src/experimental/filesystem/directory_iterator.cpp +++ b/src/experimental/filesystem/directory_iterator.cpp @@ -42,8 +42,11 @@ static file_type get_file_type(DirEntT *ent, int) { return file_type::regular; case DT_SOCK: return file_type::socket; + // Unlike in lstat, hitting "unknown" here simply means that the underlying + // filesystem doesn't support d_type. Report is as 'none' so we correctly + // set the cache to empty. case DT_UNKNOWN: - return file_type::unknown; + break; } return file_type::none; } -- GitLab From 4b61d89c1493afe3b674ba6557983037e6cdb029 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 24 Jul 2018 00:27:31 +0000 Subject: [PATCH 061/495] Revert r337727 as it caused Darwin bot failures git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337782 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 28e2eb749..6521ebbe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -378,7 +378,7 @@ endif () set(LIBCXX_COMPILER ${CMAKE_CXX_COMPILER}) set(LIBCXX_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(LIBCXX_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) -set(LIBCXX_HEADER_DIR ${LIBCXX_BINARY_DIR}) +set(LIBCXX_HEADER_DIR ${LLVM_BINARY_DIR}) set(LIBCXX_BINARY_INCLUDE_DIR "${LIBCXX_BINARY_DIR}/include/c++build") string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION -- GitLab From fbd3e84fa1ddb6651b020885c6257e7ed4179f9b Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 24 Jul 2018 03:01:02 +0000 Subject: [PATCH 062/495] Implement . Reviewed as https://reviews.llvm.org/D49338 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337804 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/CMakeLists.txt | 1 + include/module.modulemap | 4 + include/span | 606 ++++++++++++++++++ test/libcxx/double_include.sh.cpp | 1 + .../views/span.comparison/op.eq.pass.cpp | 168 +++++ .../views/span.comparison/op.ge.pass.cpp | 153 +++++ .../views/span.comparison/op.gt.pass.cpp | 154 +++++ .../views/span.comparison/op.le.pass.cpp | 153 +++++ .../views/span.comparison/op.lt.pass.cpp | 154 +++++ .../views/span.comparison/op.ne.pass.cpp | 168 +++++ .../containers/views/span.cons/array.fail.cpp | 72 +++ .../containers/views/span.cons/array.pass.cpp | 123 ++++ .../views/span.cons/assign.pass.cpp | 293 +++++++++ .../views/span.cons/container.fail.cpp | 117 ++++ .../views/span.cons/container.pass.cpp | 118 ++++ .../containers/views/span.cons/copy.pass.cpp | 71 ++ .../views/span.cons/deduct.pass.cpp | 83 +++ .../views/span.cons/default.fail.cpp | 32 + .../views/span.cons/default.pass.cpp | 82 +++ .../views/span.cons/ptr_len.fail.cpp | 63 ++ .../views/span.cons/ptr_len.pass.cpp | 113 ++++ .../views/span.cons/ptr_ptr.fail.cpp | 63 ++ .../views/span.cons/ptr_ptr.pass.cpp | 113 ++++ .../containers/views/span.cons/span.fail.cpp | 104 +++ .../containers/views/span.cons/span.pass.cpp | 142 ++++ .../views/span.cons/stdarray.pass.cpp | 111 ++++ .../containers/views/span.elem/data.pass.cpp | 121 ++++ .../views/span.elem/op_idx.pass.cpp | 119 ++++ .../views/span.iterators/begin.pass.cpp | 116 ++++ .../views/span.iterators/end.pass.cpp | 118 ++++ .../views/span.iterators/rbegin.pass.cpp | 117 ++++ .../views/span.iterators/rend.pass.cpp | 118 ++++ .../views/span.objectrep/as_bytes.pass.cpp | 78 +++ .../as_writeable_bytes.fail.cpp | 48 ++ .../as_writeable_bytes.pass.cpp | 78 +++ .../containers/views/span.obs/empty.pass.cpp | 73 +++ .../containers/views/span.obs/size.pass.cpp | 91 +++ .../views/span.obs/size_bytes.pass.cpp | 92 +++ .../containers/views/span.sub/first.pass.cpp | 136 ++++ .../containers/views/span.sub/last.pass.cpp | 136 ++++ .../views/span.sub/subspan.pass.cpp | 210 ++++++ test/std/containers/views/types.pass.cpp | 107 ++++ 42 files changed, 5020 insertions(+) create mode 100644 include/span create mode 100644 test/std/containers/views/span.comparison/op.eq.pass.cpp create mode 100644 test/std/containers/views/span.comparison/op.ge.pass.cpp create mode 100644 test/std/containers/views/span.comparison/op.gt.pass.cpp create mode 100644 test/std/containers/views/span.comparison/op.le.pass.cpp create mode 100644 test/std/containers/views/span.comparison/op.lt.pass.cpp create mode 100644 test/std/containers/views/span.comparison/op.ne.pass.cpp create mode 100644 test/std/containers/views/span.cons/array.fail.cpp create mode 100644 test/std/containers/views/span.cons/array.pass.cpp create mode 100644 test/std/containers/views/span.cons/assign.pass.cpp create mode 100644 test/std/containers/views/span.cons/container.fail.cpp create mode 100644 test/std/containers/views/span.cons/container.pass.cpp create mode 100644 test/std/containers/views/span.cons/copy.pass.cpp create mode 100644 test/std/containers/views/span.cons/deduct.pass.cpp create mode 100644 test/std/containers/views/span.cons/default.fail.cpp create mode 100644 test/std/containers/views/span.cons/default.pass.cpp create mode 100644 test/std/containers/views/span.cons/ptr_len.fail.cpp create mode 100644 test/std/containers/views/span.cons/ptr_len.pass.cpp create mode 100644 test/std/containers/views/span.cons/ptr_ptr.fail.cpp create mode 100644 test/std/containers/views/span.cons/ptr_ptr.pass.cpp create mode 100644 test/std/containers/views/span.cons/span.fail.cpp create mode 100644 test/std/containers/views/span.cons/span.pass.cpp create mode 100644 test/std/containers/views/span.cons/stdarray.pass.cpp create mode 100644 test/std/containers/views/span.elem/data.pass.cpp create mode 100644 test/std/containers/views/span.elem/op_idx.pass.cpp create mode 100644 test/std/containers/views/span.iterators/begin.pass.cpp create mode 100644 test/std/containers/views/span.iterators/end.pass.cpp create mode 100644 test/std/containers/views/span.iterators/rbegin.pass.cpp create mode 100644 test/std/containers/views/span.iterators/rend.pass.cpp create mode 100644 test/std/containers/views/span.objectrep/as_bytes.pass.cpp create mode 100644 test/std/containers/views/span.objectrep/as_writeable_bytes.fail.cpp create mode 100644 test/std/containers/views/span.objectrep/as_writeable_bytes.pass.cpp create mode 100644 test/std/containers/views/span.obs/empty.pass.cpp create mode 100644 test/std/containers/views/span.obs/size.pass.cpp create mode 100644 test/std/containers/views/span.obs/size_bytes.pass.cpp create mode 100644 test/std/containers/views/span.sub/first.pass.cpp create mode 100644 test/std/containers/views/span.sub/last.pass.cpp create mode 100644 test/std/containers/views/span.sub/subspan.pass.cpp create mode 100644 test/std/containers/views/types.pass.cpp diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index e44ff3ef3..c60e61e6d 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -128,6 +128,7 @@ set(files set setjmp.h shared_mutex + span sstream stack stdbool.h diff --git a/include/module.modulemap b/include/module.modulemap index 70f82a775..e17c3a2f6 100644 --- a/include/module.modulemap +++ b/include/module.modulemap @@ -559,6 +559,10 @@ module std [system] { header "experimental/set" export * } + module span { + header "span" + export * + } module string { header "experimental/string" export * diff --git a/include/span b/include/span new file mode 100644 index 000000000..b1a13dd02 --- /dev/null +++ b/include/span @@ -0,0 +1,606 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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_SPAN +#define _LIBCPP_SPAN + +/* + span synopsis + +namespace std { + +// constants +inline constexpr ptrdiff_t dynamic_extent = -1; + +// [views.span], class template span +template + class span; + +// [span.comparison], span comparison operators +template + constexpr bool operator==(span l, span r); +template + constexpr bool operator!=(span l, span r); +template + constexpr bool operator<(span l, span r); +template + constexpr bool operator<=(span l, span r); +template + constexpr bool operator>(span l, span r); +template + constexpr bool operator>=(span l, span r); + +// [span.objectrep], views of object representation +template + span(sizeof(ElementType)) * Extent))> as_bytes(span s) noexcept; + +template + span< byte, ((Extent == dynamic_extent) ? dynamic_extent : + (static_cast(sizeof(ElementType)) * Extent))> as_writable_bytes(span s) noexcept; + + +namespace std { +template +class span { +public: + // constants and types + using element_type = ElementType; + using value_type = remove_cv_t; + using index_type = ptrdiff_t; + using difference_type = ptrdiff_t; + using pointer = element_type*; + using reference = element_type&; + using iterator = implementation-defined; + using const_iterator = implementation-defined; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + static constexpr index_type extent = Extent; + + // [span.cons], span constructors, copy, assignment, and destructor + constexpr span() noexcept; + constexpr span(pointer ptr, index_type count); + constexpr span(pointer firstElem, pointer lastElem); + template + constexpr span(element_type (&arr)[N]) noexcept; + template + constexpr span(array& arr) noexcept; + template + constexpr span(const array& arr) noexcept; + template + constexpr span(Container& cont); + template + constexpr span(const Container& cont); + constexpr span(const span& other) noexcept = default; + template + constexpr span(const span& s) noexcept; + ~span() noexcept = default; + constexpr span& operator=(const span& other) noexcept = default; + + // [span.sub], span subviews + template + constexpr span first() const; + template + constexpr span last() const; + template + constexpr span subspan() const; + + constexpr span first(index_type count) const; + constexpr span last(index_type count) const; + constexpr span subspan(index_type offset, index_type count = dynamic_extent) const; + + // [span.obs], span observers + constexpr index_type size() const noexcept; + constexpr index_type size_bytes() const noexcept; + constexpr bool empty() const noexcept; + + // [span.elem], span element access + constexpr reference operator[](index_type idx) const; + constexpr reference operator()(index_type idx) const; + constexpr pointer data() const noexcept; + + // [span.iterators], span iterator support + constexpr iterator begin() const noexcept; + constexpr iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + +private: + pointer data_; // exposition only + index_type size_; // exposition only +}; + +template + span(T (&)[N]) -> span; + +template + span(array&) -> span; + +template + span(const array&) -> span; + +template + span(Container&) -> span; + +template + span(const Container&) -> span; + +} // namespace std + +*/ + +#include // for ptrdiff_t +#include // for iterators +#include // for array +#include // for remove_cv, etc +#include // for byte + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +inline constexpr ptrdiff_t dynamic_extent = -1; +template class span; + + +template +struct __is_span_impl : public false_type {}; + +template +struct __is_span_impl> : public true_type {}; + +template +struct __is_span : public __is_span_impl> {}; + +template +struct __is_std_array_impl : public false_type {}; + +template +struct __is_std_array_impl> : public true_type {}; + +template +struct __is_std_array : public __is_std_array_impl> {}; + +template +struct __is_span_compatible_container : public false_type {}; + +template +struct __is_span_compatible_container<_Tp, _ElementType, + void_t< + // is not a specialization of span + typename enable_if::value, nullptr_t>::type, + // is not a specialization of array + typename enable_if::value, nullptr_t>::type, + // is_array_v is false, + typename enable_if, nullptr_t>::type, + // data(cont) and size(cont) are well formed + decltype(data(declval<_Tp>())), + decltype(size(declval<_Tp>())), + // remove_pointer_t(*)[] is convertible to ElementType(*)[] + typename enable_if< + is_convertible_v()))>(*)[], + _ElementType(*)[]>, + nullptr_t>::type + >> + : public true_type {}; + + +template +class _LIBCPP_TEMPLATE_VIS span { +public: +// constants and types + using element_type = _Tp; + using value_type = remove_cv_t<_Tp>; + using index_type = ptrdiff_t; + using difference_type = ptrdiff_t; + using pointer = _Tp *; + using const_pointer = const _Tp *; // not in standard + using reference = _Tp &; + using const_reference = const _Tp &; // not in standard + using iterator = __wrap_iter; + using const_iterator = __wrap_iter; + using reverse_iterator = _VSTD::reverse_iterator; + using const_reverse_iterator = _VSTD::reverse_iterator; + + 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 + _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} + { static_assert(_Extent == 0, "Can't default construct a statically sized span with size > 0"); } + + constexpr span (const span&) noexcept = default; + constexpr span& operator=(const span&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr} + { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); } + _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f} + { (void)__l; _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); } + + _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent]) noexcept : __data{__arr} {} + _LIBCPP_INLINE_VISIBILITY constexpr span( array& __arr) noexcept : __data{__arr.data()} {} + _LIBCPP_INLINE_VISIBILITY constexpr span(const array& __arr) noexcept : __data{__arr.data()} {} + + template + inline _LIBCPP_INLINE_VISIBILITY + 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))"); } + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(const _Container& __c, + enable_if_t<__is_span_compatible_container::value, nullptr_t> = nullptr) + : __data{_VSTD::data(__c)} + { _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (const container)"); } + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(const span<_OtherElementType, _Extent>& __other, + enable_if_t< + is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, + nullptr_t> = nullptr) + : __data{__other.data()} {} + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(const span<_OtherElementType, dynamic_extent>& __other, + enable_if_t< + is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, + nullptr_t> = nullptr) noexcept + : __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); } + + +// ~span() noexcept = default; + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span first() const noexcept + { + static_assert(_Count >= 0, "Count must be >= 0 in span::first()"); + static_assert(_Count <= _Extent, "Count out of range in span::first()"); + return {data(), _Count}; + } + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span last() const noexcept + { + static_assert(_Count >= 0, "Count must be >= 0 in span::last()"); + static_assert(_Count <= _Extent, "Count out of range in span::last()"); + return {data() + size() - _Count, _Count}; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr span first(index_type __count) const noexcept + { + _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)"); + return {data(), __count}; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr span last(index_type __count) const noexcept + { + _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)"); + return {data() + size() - __count, __count}; + } + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr auto subspan() const noexcept + -> span + { + _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()"); + return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; + } + + + inline _LIBCPP_INLINE_VISIBILITY + constexpr span + 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) + return {data() + __offset, size() - __offset}; + _LIBCPP_ASSERT(__offset + __count <= size(), "count + offset out of range in span::subspan(offset, count)"); + return {data() + __offset, __count}; + } + + _LIBCPP_INLINE_VISIBILITY constexpr index_type size() const noexcept { return _Extent; } + _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return _Extent * sizeof(element_type); } + _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return _Extent == 0; } + + _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept + { + _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span[] index out of bounds"); + return __data[__idx]; + } + + _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept + { + _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span() index out of bounds"); + return __data[__idx]; + } + + _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } + +// [span.iter], span iterator support + _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); } + _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); } + _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } + _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } + + _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept + { + pointer __p = __data; + __data = __other.__data; + __other.__data = __p; + } + + _LIBCPP_INLINE_VISIBILITY span __as_bytes() const noexcept + { return {reinterpret_cast(data()), size_bytes()}; } + + _LIBCPP_INLINE_VISIBILITY span __as_writeable_bytes() const noexcept + { return {reinterpret_cast(data()), size_bytes()}; } + +private: + pointer __data; + +}; + + +template +class _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> { +private: + +public: +// constants and types + using element_type = _Tp; + using value_type = remove_cv_t<_Tp>; + using index_type = ptrdiff_t; + using difference_type = ptrdiff_t; + using pointer = _Tp *; + using const_pointer = const _Tp *; // not in standard + using reference = _Tp &; + using const_reference = const _Tp &; // not in standard + using iterator = __wrap_iter; + using const_iterator = __wrap_iter; + using reverse_iterator = _VSTD::reverse_iterator; + using const_reverse_iterator = _VSTD::reverse_iterator; + + static constexpr index_type extent = dynamic_extent; + +// [span.cons], span constructors, copy, assignment, and destructor + _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {} + + constexpr span (const span&) noexcept = default; + constexpr span& operator=(const span&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}, __size{__count} {} + _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{distance(__f, __l)} {} + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(element_type (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} {} + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(array& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(const array& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span( _Container& __c, + enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr) + : __data{_VSTD::data(__c)}, __size{(index_type) _VSTD::size(__c)} {} + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(const _Container& __c, + enable_if_t<__is_span_compatible_container::value, nullptr_t> = nullptr) + : __data{_VSTD::data(__c)}, __size{(index_type) _VSTD::size(__c)} {} + + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(const span<_OtherElementType, _OtherExtent>& __other, + enable_if_t< + is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, + nullptr_t> = nullptr) noexcept + : __data{__other.data()}, __size{__other.size()} {} + +// ~span() noexcept = default; + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span first() const noexcept + { + static_assert(_Count >= 0); + _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()"); + return {data(), _Count}; + } + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span last() const noexcept + { + static_assert(_Count >= 0); + _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()"); + return {data() + size() - _Count, _Count}; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr span first(index_type __count) const noexcept + { + _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)"); + return {data(), __count}; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr span last (index_type __count) const noexcept + { + _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)"); + return {data() + size() - __count, __count}; + } + + template + inline _LIBCPP_INLINE_VISIBILITY + constexpr span<_Tp, dynamic_extent> subspan() const noexcept + { + _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()"); + _LIBCPP_ASSERT(_Count == dynamic_extent || _Offset + _Count <= size(), "Count out of range in span::subspan()"); + return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; + } + + constexpr span + 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) + return {data() + __offset, size() - __offset}; + _LIBCPP_ASSERT(__offset + __count <= size(), "Offset + count out of range in span::subspan(offset, count)"); + return {data() + __offset, __count}; + } + + _LIBCPP_INLINE_VISIBILITY constexpr index_type size() const noexcept { return __size; } + _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return __size * sizeof(element_type); } + _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return __size == 0; } + + _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept + { + _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span[] index out of bounds"); + return __data[__idx]; + } + + _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept + { + _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span() index out of bounds"); + return __data[__idx]; + } + + _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } + +// [span.iter], span iterator support + _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); } + _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); } + _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } + _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } + + _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept + { + pointer __p = __data; + __data = __other.__data; + __other.__data = __p; + + index_type __sz = __size; + __size = __other.__size; + __other.__size = __sz; + } + + _LIBCPP_INLINE_VISIBILITY span __as_bytes() const noexcept + { return {reinterpret_cast(data()), size_bytes()}; } + + _LIBCPP_INLINE_VISIBILITY span __as_writeable_bytes() const noexcept + { return {reinterpret_cast(data()), size_bytes()}; } + +private: + pointer __data; + index_type __size; +}; + +template + constexpr bool + operator==(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return equal(__lhs.begin(), __lhs.end(), __rhs.begin(), __rhs.end()); } + +template + constexpr bool + operator!=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return !(__rhs == __lhs); } + +template + 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 + constexpr bool + operator<=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return !(__rhs < __lhs); } + +template + constexpr bool + operator> (const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return __rhs < __lhs; } + +template + constexpr bool + operator>=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return !(__lhs < __rhs); } + +// as_bytes & as_writeable_bytes +template + auto as_bytes(span<_Tp, _Extent> __s) noexcept + -> decltype(__s.__as_bytes()) + { return __s.__as_bytes(); } + +template + auto as_writeable_bytes(span<_Tp, _Extent> __s) noexcept + -> typename enable_if, decltype(__s.__as_writeable_bytes())>::type + { return __s.__as_writeable_bytes(); } + +template + constexpr void swap(span<_Tp, _Extent> &__lhs, span<_Tp, _Extent> &__rhs) noexcept + { __lhs.swap(__rhs); } + + +// Deduction guides +template + span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>; + +template + span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>; + +template + span(const array<_Tp, _Sz>&) -> span; + +template + span(_Container&) -> span; + +template + span(const _Container&) -> span; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_SPAN diff --git a/test/libcxx/double_include.sh.cpp b/test/libcxx/double_include.sh.cpp index 0f2d1e089..dfc3d0116 100644 --- a/test/libcxx/double_include.sh.cpp +++ b/test/libcxx/double_include.sh.cpp @@ -102,6 +102,7 @@ #ifndef _LIBCPP_HAS_NO_THREADS #include #endif +#include #include #include #include diff --git a/test/std/containers/views/span.comparison/op.eq.pass.cpp b/test/std/containers/views/span.comparison/op.eq.pass.cpp new file mode 100644 index 000000000..963054580 --- /dev/null +++ b/test/std/containers/views/span.comparison/op.eq.pass.cpp @@ -0,0 +1,168 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr bool operator==(span l, span r); +// +// +// Effects: Equivalent to: return equal(l.begin(), l.end(), r.begin(), r.end()); +// + +#include +#include + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span csp0d{}; + constexpr std::span csp1d{iArr1, 10}; + constexpr std::span csp2d{iArr1 + 3, 2}; + constexpr std::span csp3d{iArr1 + 1, 2}; + constexpr std::span csp4d{iArr1 + 6, 2}; + + constexpr std::span csp0s{}; + constexpr std::span csp1s{iArr1, 10}; + constexpr std::span csp2s{iArr1 + 3, 2}; + constexpr std::span csp3s{iArr1 + 1, 2}; + constexpr std::span csp4s{iArr1 + 6, 2}; + + static_assert( (csp0d == csp0d), ""); + static_assert( (csp0s == csp0s), ""); + static_assert( (csp0s == csp0d), ""); + static_assert( (csp0d == csp0s), ""); + + static_assert(!(csp0d == csp1d), ""); + static_assert(!(csp0s == csp1s), ""); + static_assert(!(csp0s == csp1d), ""); + static_assert(!(csp0d == csp1s), ""); + + static_assert( (csp1d == csp1s), ""); + static_assert( (csp1s == csp1d), ""); + + static_assert( (csp2d == csp3d), ""); + static_assert( (csp2s == csp3s), ""); + static_assert( (csp2d == csp3s), ""); + static_assert( (csp2s == csp3d), ""); + + static_assert( (csp2d == csp3d), ""); + static_assert( (csp2s == csp3s), ""); + static_assert( (csp2d == csp3s), ""); + static_assert( (csp2s == csp3d), ""); + + static_assert(!(csp2d == csp4d), ""); + static_assert(!(csp2s == csp4s), ""); + static_assert(!(csp2d == csp4s), ""); + static_assert(!(csp2s == csp4d), ""); + + static_assert(!(csp4d == csp2d), ""); + static_assert(!(csp4s == csp2s), ""); + static_assert(!(csp4d == csp2s), ""); + static_assert(!(csp4s == csp2d), ""); + + std::span sp0d{}; + std::span sp1d{iArr2, 10}; + std::span sp2d{iArr2 + 3, 2}; + std::span sp3d{iArr2 + 1, 2}; + std::span sp4d{iArr2 + 6, 2}; + + std::span sp0s{}; + std::span sp1s{iArr2, 10}; + std::span sp2s{iArr2 + 3, 2}; + std::span sp3s{iArr2 + 1, 2}; + std::span sp4s{iArr2 + 6, 2}; + + assert( (sp0d == sp0d)); + assert( (sp0s == sp0s)); + assert( (sp0s == sp0d)); + assert( (sp0d == sp0s)); + + assert(!(sp0d == sp1d)); + assert(!(sp0s == sp1s)); + assert(!(sp0s == sp1d)); + assert(!(sp0d == sp1s)); + + assert( (sp1d == sp1s)); + assert( (sp1s == sp1d)); + + assert( (sp2d == sp3d)); + assert( (sp2s == sp3s)); + assert( (sp2d == sp3s)); + assert( (sp2s == sp3d)); + + assert( (sp2d == sp3d)); + assert( (sp2s == sp3s)); + assert( (sp2d == sp3s)); + assert( (sp2s == sp3d)); + + assert(!(sp2d == sp4d)); + assert(!(sp2s == sp4s)); + assert(!(sp2d == sp4s)); + assert(!(sp2s == sp4d)); + + assert(!(sp4d == sp2d)); + assert(!(sp4s == sp2s)); + assert(!(sp4d == sp2s)); + assert(!(sp4s == sp2d)); + +// cross type comparisons + assert( (csp0d == sp0d)); + assert( (csp0s == sp0s)); + assert( (csp0s == sp0d)); + assert( (csp0d == sp0s)); + + assert(!(csp0d == sp1d)); + assert(!(csp0s == sp1s)); + assert(!(csp0s == sp1d)); + assert(!(csp0d == sp1s)); + + assert( (csp1d == sp1s)); + assert( (csp1s == sp1d)); + + assert( (csp2d == sp3d)); + assert( (csp2s == sp3s)); + assert( (csp2d == sp3s)); + assert( (csp2s == sp3d)); + + assert( (csp2d == sp3d)); + assert( (csp2s == sp3s)); + assert( (csp2d == sp3s)); + assert( (csp2s == sp3d)); + + assert(!(csp2d == sp4d)); + assert(!(csp2s == sp4s)); + assert(!(csp2d == sp4s)); + assert(!(csp2s == sp4d)); + + assert(!(csp4d == sp2d)); + assert(!(csp4s == sp2s)); + assert(!(csp4d == sp2s)); + assert(!(csp4s == sp2d)); + +// More cross-type comparisons (int vs float) + static_assert(std::span{fArr1} == std::span{iArr1}, ""); + static_assert(std::span{iArr1} == std::span{fArr1}, ""); + assert(std::span{fArr2} == std::span{iArr2}); + assert(std::span{iArr2} == std::span{fArr2}); + + static_assert(!(std::span{iArr1, 9} == std::span{fArr1, 8}), ""); +} \ No newline at end of file diff --git a/test/std/containers/views/span.comparison/op.ge.pass.cpp b/test/std/containers/views/span.comparison/op.ge.pass.cpp new file mode 100644 index 000000000..8ec1b9a59 --- /dev/null +++ b/test/std/containers/views/span.comparison/op.ge.pass.cpp @@ -0,0 +1,153 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr bool operator>=(span l, span r); +// +// +// Effects: Equivalent to: return !(l < r); +// + +#include +#include + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span csp0d{}; + constexpr std::span csp1d{iArr1, 10}; + constexpr std::span csp2d{iArr1 + 3, 2}; + constexpr std::span csp3d{iArr1 + 1, 2}; + constexpr std::span csp4d{iArr1 + 6, 2}; + + constexpr std::span csp0s{}; + constexpr std::span csp1s{iArr1, 10}; + constexpr std::span csp2s{iArr1 + 3, 2}; + constexpr std::span csp3s{iArr1 + 1, 2}; + constexpr std::span csp4s{iArr1 + 6, 2}; + + static_assert( (csp0d >= csp0d), ""); + static_assert( (csp0s >= csp0s), ""); + static_assert( (csp0s >= csp0d), ""); + static_assert( (csp0d >= csp0s), ""); + + static_assert(!(csp0d >= csp1d), ""); + static_assert(!(csp0s >= csp1s), ""); + static_assert(!(csp0s >= csp1d), ""); + static_assert(!(csp0d >= csp1s), ""); + + static_assert( (csp1d >= csp1s), ""); + static_assert( (csp1s >= csp1d), ""); + + static_assert( (csp2d >= csp3d), ""); + static_assert( (csp2s >= csp3s), ""); + static_assert( (csp2d >= csp3s), ""); + static_assert( (csp2s >= csp3d), ""); + + static_assert(!(csp2d >= csp4d), ""); + static_assert(!(csp2s >= csp4s), ""); + static_assert(!(csp2d >= csp4s), ""); + static_assert(!(csp2s >= csp4d), ""); + + static_assert( (csp4d >= csp2d), ""); + static_assert( (csp4s >= csp2s), ""); + static_assert( (csp4d >= csp2s), ""); + static_assert( (csp4s >= csp2d), ""); + + std::span sp0d{}; + std::span sp1d{iArr2, 10}; + std::span sp2d{iArr2 + 3, 2}; + std::span sp3d{iArr2 + 1, 2}; + std::span sp4d{iArr2 + 6, 2}; + + std::span sp0s{}; + std::span sp1s{iArr2, 10}; + std::span sp2s{iArr2 + 3, 2}; + std::span sp3s{iArr2 + 1, 2}; + std::span sp4s{iArr2 + 6, 2}; + + assert( (sp0d >= sp0d)); + assert( (sp0s >= sp0s)); + assert( (sp0s >= sp0d)); + assert( (sp0d >= sp0s)); + + assert(!(sp0d >= sp1d)); + assert(!(sp0s >= sp1s)); + assert(!(sp0s >= sp1d)); + assert(!(sp0d >= sp1s)); + + assert( (sp1d >= sp1s)); + assert( (sp1s >= sp1d)); + + assert( (sp2d >= sp3d)); + assert( (sp2s >= sp3s)); + assert( (sp2d >= sp3s)); + assert( (sp2s >= sp3d)); + + assert(!(sp2d >= sp4d)); + assert(!(sp2s >= sp4s)); + assert(!(sp2d >= sp4s)); + assert(!(sp2s >= sp4d)); + + assert( (sp4d > sp2d)); + assert( (sp4s > sp2s)); + assert( (sp4d > sp2s)); + assert( (sp4s > sp2d)); + +// cross type comparisons + assert( (csp0d >= sp0d)); + assert( (csp0s >= sp0s)); + assert( (csp0s >= sp0d)); + assert( (csp0d >= sp0s)); + + assert(!(csp0d >= sp1d)); + assert(!(csp0s >= sp1s)); + assert(!(csp0s >= sp1d)); + assert(!(csp0d >= sp1s)); + + assert( (csp1d >= sp1s)); + assert( (csp1s >= sp1d)); + + assert( (csp2d >= sp3d)); + assert( (csp2s >= sp3s)); + assert( (csp2d >= sp3s)); + assert( (csp2s >= sp3d)); + + assert(!(csp2d >= sp4d)); + assert(!(csp2s >= sp4s)); + assert(!(csp2d >= sp4s)); + assert(!(csp2s >= sp4d)); + + assert( (csp4d > sp2d)); + assert( (csp4s > sp2s)); + assert( (csp4d > sp2s)); + assert( (csp4s > sp2d)); + +// More cross-type comparisons (int vs float) + static_assert(!(std::span{fArr1, 8} >= std::span{iArr1, 9}), ""); + static_assert(!(std::span{iArr1, 8} >= std::span{fArr1, 9}), ""); + assert( (std::span{fArr2} >= std::span{iArr2})); + assert( (std::span{iArr2} >= std::span{fArr2})); + + static_assert( (std::span{iArr1, 9} >= std::span{fArr1, 8}), ""); +} diff --git a/test/std/containers/views/span.comparison/op.gt.pass.cpp b/test/std/containers/views/span.comparison/op.gt.pass.cpp new file mode 100644 index 000000000..345a291a6 --- /dev/null +++ b/test/std/containers/views/span.comparison/op.gt.pass.cpp @@ -0,0 +1,154 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr bool operator>(span l, span r); +// +// +// Effects: Equivalent to: return (r < l); +// + +#include +#include + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span csp0d{}; + constexpr std::span csp1d{iArr1, 10}; + constexpr std::span csp2d{iArr1 + 3, 2}; + constexpr std::span csp3d{iArr1 + 1, 2}; + constexpr std::span csp4d{iArr1 + 6, 2}; + + constexpr std::span csp0s{}; + constexpr std::span csp1s{iArr1, 10}; + constexpr std::span csp2s{iArr1 + 3, 2}; + constexpr std::span csp3s{iArr1 + 1, 2}; + constexpr std::span csp4s{iArr1 + 6, 2}; + + static_assert(!(csp0d > csp0d), ""); + static_assert(!(csp0s > csp0s), ""); + static_assert(!(csp0s > csp0d), ""); + static_assert(!(csp0d > csp0s), ""); + + static_assert(!(csp0d > csp1d), ""); + static_assert(!(csp0s > csp1s), ""); + static_assert(!(csp0s > csp1d), ""); + static_assert(!(csp0d > csp1s), ""); + + static_assert(!(csp1d > csp1s), ""); + static_assert(!(csp1s > csp1d), ""); + + static_assert(!(csp2d > csp3d), ""); + static_assert(!(csp2s > csp3s), ""); + static_assert(!(csp2d > csp3s), ""); + static_assert(!(csp2s > csp3d), ""); + + static_assert(!(csp2d > csp4d), ""); + static_assert(!(csp2s > csp4s), ""); + static_assert(!(csp2d > csp4s), ""); + static_assert(!(csp2s > csp4d), ""); + + static_assert( (csp4d > csp2d), ""); + static_assert( (csp4s > csp2s), ""); + static_assert( (csp4d > csp2s), ""); + static_assert( (csp4s > csp2d), ""); + + std::span sp0d{}; + std::span sp1d{iArr2, 10}; + std::span sp2d{iArr2 + 3, 2}; + std::span sp3d{iArr2 + 1, 2}; + std::span sp4d{iArr2 + 6, 2}; + + std::span sp0s{}; + std::span sp1s{iArr2, 10}; + std::span sp2s{iArr2 + 3, 2}; + std::span sp3s{iArr2 + 1, 2}; + std::span sp4s{iArr2 + 6, 2}; + + assert(!(sp0d > sp0d)); + assert(!(sp0s > sp0s)); + assert(!(sp0s > sp0d)); + assert(!(sp0d > sp0s)); + + assert(!(sp0d > sp1d)); + assert(!(sp0s > sp1s)); + assert(!(sp0s > sp1d)); + assert(!(sp0d > sp1s)); + + assert(!(sp1d > sp1s)); + assert(!(sp1s > sp1d)); + + assert(!(sp2d > sp3d)); + assert(!(sp2s > sp3s)); + assert(!(sp2d > sp3s)); + assert(!(sp2s > sp3d)); + + assert(!(sp2d > sp4d)); + assert(!(sp2s > sp4s)); + assert(!(sp2d > sp4s)); + assert(!(sp2s > sp4d)); + + assert( (sp4d > sp2d)); + assert( (sp4s > sp2s)); + assert( (sp4d > sp2s)); + assert( (sp4s > sp2d)); + +// cross type comparisons + assert(!(csp0d > sp0d)); + assert(!(csp0s > sp0s)); + assert(!(csp0s > sp0d)); + assert(!(csp0d > sp0s)); + + assert(!(csp0d > sp1d)); + assert(!(csp0s > sp1s)); + assert(!(csp0s > sp1d)); + assert(!(csp0d > sp1s)); + + assert(!(csp1d > sp1s)); + assert(!(csp1s > sp1d)); + + assert(!(csp2d > sp3d)); + assert(!(csp2s > sp3s)); + assert(!(csp2d > sp3s)); + assert(!(csp2s > sp3d)); + + assert(!(csp2d > sp4d)); + assert(!(csp2s > sp4s)); + assert(!(csp2d > sp4s)); + assert(!(csp2s > sp4d)); + + assert( (csp4d > sp2d)); + assert( (csp4s > sp2s)); + assert( (csp4d > sp2s)); + assert( (csp4s > sp2d)); + + +// More cross-type comparisons (int vs float) + static_assert(!(std::span{fArr1, 8} > std::span{iArr1, 9}), ""); + static_assert(!(std::span{iArr1, 8} > std::span{fArr1, 9}), ""); + assert(!(std::span{fArr2} > std::span{iArr2})); + assert(!(std::span{iArr2} > std::span{fArr2})); + + static_assert( (std::span{iArr1, 9} > std::span{fArr1, 8}), ""); +} \ No newline at end of file diff --git a/test/std/containers/views/span.comparison/op.le.pass.cpp b/test/std/containers/views/span.comparison/op.le.pass.cpp new file mode 100644 index 000000000..f2fbc8609 --- /dev/null +++ b/test/std/containers/views/span.comparison/op.le.pass.cpp @@ -0,0 +1,153 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr bool operator<=(span l, span r); +// +// +// Effects: Equivalent to: return !(r < l); +// + +#include +#include + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span csp0d{}; + constexpr std::span csp1d{iArr1, 10}; + constexpr std::span csp2d{iArr1 + 3, 2}; + constexpr std::span csp3d{iArr1 + 1, 2}; + constexpr std::span csp4d{iArr1 + 6, 2}; + + constexpr std::span csp0s{}; + constexpr std::span csp1s{iArr1, 10}; + constexpr std::span csp2s{iArr1 + 3, 2}; + constexpr std::span csp3s{iArr1 + 1, 2}; + constexpr std::span csp4s{iArr1 + 6, 2}; + + static_assert( (csp0d <= csp0d), ""); + static_assert( (csp0s <= csp0s), ""); + static_assert( (csp0s <= csp0d), ""); + static_assert( (csp0d <= csp0s), ""); + + static_assert( (csp0d <= csp1d), ""); + static_assert( (csp0s <= csp1s), ""); + static_assert( (csp0s <= csp1d), ""); + static_assert( (csp0d <= csp1s), ""); + + static_assert( (csp1d <= csp1s), ""); + static_assert( (csp1s <= csp1d), ""); + + static_assert( (csp2d <= csp3d), ""); + static_assert( (csp2s <= csp3s), ""); + static_assert( (csp2d <= csp3s), ""); + static_assert( (csp2s <= csp3d), ""); + + static_assert( (csp2d <= csp4d), ""); + static_assert( (csp2s <= csp4s), ""); + static_assert( (csp2d <= csp4s), ""); + static_assert( (csp2s <= csp4d), ""); + + static_assert(!(csp4d <= csp2d), ""); + static_assert(!(csp4s <= csp2s), ""); + static_assert(!(csp4d <= csp2s), ""); + static_assert(!(csp4s <= csp2d), ""); + + std::span sp0d{}; + std::span sp1d{iArr2, 10}; + std::span sp2d{iArr2 + 3, 2}; + std::span sp3d{iArr2 + 1, 2}; + std::span sp4d{iArr2 + 6, 2}; + + std::span sp0s{}; + std::span sp1s{iArr2, 10}; + std::span sp2s{iArr2 + 3, 2}; + std::span sp3s{iArr2 + 1, 2}; + std::span sp4s{iArr2 + 6, 2}; + + assert( (sp0d <= sp0d)); + assert( (sp0s <= sp0s)); + assert( (sp0s <= sp0d)); + assert( (sp0d <= sp0s)); + + assert( (sp0d <= sp1d)); + assert( (sp0s <= sp1s)); + assert( (sp0s <= sp1d)); + assert( (sp0d <= sp1s)); + + assert( (sp1d <= sp1s)); + assert( (sp1s <= sp1d)); + + assert( (sp2d <= sp3d)); + assert( (sp2s <= sp3s)); + assert( (sp2d <= sp3s)); + assert( (sp2s <= sp3d)); + + assert( (sp2d <= sp4d)); + assert( (sp2s <= sp4s)); + assert( (sp2d <= sp4s)); + assert( (sp2s <= sp4d)); + + assert(!(sp4d <= sp2d)); + assert(!(sp4s <= sp2s)); + assert(!(sp4d <= sp2s)); + assert(!(sp4s <= sp2d)); + +// cross type comparisons + assert( (csp0d <= sp0d)); + assert( (csp0s <= sp0s)); + assert( (csp0s <= sp0d)); + assert( (csp0d <= sp0s)); + + assert( (csp0d <= sp1d)); + assert( (csp0s <= sp1s)); + assert( (csp0s <= sp1d)); + assert( (csp0d <= sp1s)); + + assert( (csp1d <= sp1s)); + assert( (csp1s <= sp1d)); + + assert( (csp2d <= sp3d)); + assert( (csp2s <= sp3s)); + assert( (csp2d <= sp3s)); + assert( (csp2s <= sp3d)); + + assert( (csp2d <= sp4d)); + assert( (csp2s <= sp4s)); + assert( (csp2d <= sp4s)); + assert( (csp2s <= sp4d)); + + assert(!(csp4d <= sp2d)); + assert(!(csp4s <= sp2s)); + assert(!(csp4d <= sp2s)); + assert(!(csp4s <= sp2d)); + +// More cross-type comparisons (int vs float) + static_assert(std::span{fArr1, 8} <= std::span{iArr1, 9}, ""); + static_assert(std::span{iArr1, 8} <= std::span{fArr1, 9}, ""); + assert( (std::span{fArr2} <= std::span{iArr2})); + assert( (std::span{iArr2} <= std::span{fArr2})); + + static_assert(!(std::span{iArr1, 9} <= std::span{fArr1, 8}), ""); +} \ No newline at end of file diff --git a/test/std/containers/views/span.comparison/op.lt.pass.cpp b/test/std/containers/views/span.comparison/op.lt.pass.cpp new file mode 100644 index 000000000..1a7de292e --- /dev/null +++ b/test/std/containers/views/span.comparison/op.lt.pass.cpp @@ -0,0 +1,154 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr bool operator<(span l, span r); +// +// +// Effects: Equivalent to: +// return lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); +// + +#include +#include + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span csp0d{}; + constexpr std::span csp1d{iArr1, 10}; + constexpr std::span csp2d{iArr1 + 3, 2}; + constexpr std::span csp3d{iArr1 + 1, 2}; + constexpr std::span csp4d{iArr1 + 6, 2}; + + constexpr std::span csp0s{}; + constexpr std::span csp1s{iArr1, 10}; + constexpr std::span csp2s{iArr1 + 3, 2}; + constexpr std::span csp3s{iArr1 + 1, 2}; + constexpr std::span csp4s{iArr1 + 6, 2}; + + static_assert(!(csp0d < csp0d), ""); + static_assert(!(csp0s < csp0s), ""); + static_assert(!(csp0s < csp0d), ""); + static_assert(!(csp0d < csp0s), ""); + + static_assert( (csp0d < csp1d), ""); + static_assert( (csp0s < csp1s), ""); + static_assert( (csp0s < csp1d), ""); + static_assert( (csp0d < csp1s), ""); + + static_assert(!(csp1d < csp1s), ""); + static_assert(!(csp1s < csp1d), ""); + + static_assert(!(csp2d < csp3d), ""); + static_assert(!(csp2s < csp3s), ""); + static_assert(!(csp2d < csp3s), ""); + static_assert(!(csp2s < csp3d), ""); + + static_assert( (csp2d < csp4d), ""); + static_assert( (csp2s < csp4s), ""); + static_assert( (csp2d < csp4s), ""); + static_assert( (csp2s < csp4d), ""); + + static_assert(!(csp4d < csp2d), ""); + static_assert(!(csp4s < csp2s), ""); + static_assert(!(csp4d < csp2s), ""); + static_assert(!(csp4s < csp2d), ""); + + std::span sp0d{}; + std::span sp1d{iArr2, 10}; + std::span sp2d{iArr2 + 3, 2}; + std::span sp3d{iArr2 + 1, 2}; + std::span sp4d{iArr2 + 6, 2}; + + std::span sp0s{}; + std::span sp1s{iArr2, 10}; + std::span sp2s{iArr2 + 3, 2}; + std::span sp3s{iArr2 + 1, 2}; + std::span sp4s{iArr2 + 6, 2}; + + assert(!(sp0d < sp0d)); + assert(!(sp0s < sp0s)); + assert(!(sp0s < sp0d)); + assert(!(sp0d < sp0s)); + + assert( (sp0d < sp1d)); + assert( (sp0s < sp1s)); + assert( (sp0s < sp1d)); + assert( (sp0d < sp1s)); + + assert(!(sp1d < sp1s)); + assert(!(sp1s < sp1d)); + + assert(!(sp2d < sp3d)); + assert(!(sp2s < sp3s)); + assert(!(sp2d < sp3s)); + assert(!(sp2s < sp3d)); + + assert( (sp2d < sp4d)); + assert( (sp2s < sp4s)); + assert( (sp2d < sp4s)); + assert( (sp2s < sp4d)); + + assert(!(sp4d < sp2d)); + assert(!(sp4s < sp2s)); + assert(!(sp4d < sp2s)); + assert(!(sp4s < sp2d)); + +// cross type comparisons + assert(!(csp0d < sp0d)); + assert(!(csp0s < sp0s)); + assert(!(csp0s < sp0d)); + assert(!(csp0d < sp0s)); + + assert( (csp0d < sp1d)); + assert( (csp0s < sp1s)); + assert( (csp0s < sp1d)); + assert( (csp0d < sp1s)); + + assert(!(csp1d < sp1s)); + assert(!(csp1s < sp1d)); + + assert(!(csp2d < sp3d)); + assert(!(csp2s < sp3s)); + assert(!(csp2d < sp3s)); + assert(!(csp2s < sp3d)); + + assert( (csp2d < sp4d)); + assert( (csp2s < sp4s)); + assert( (csp2d < sp4s)); + assert( (csp2s < sp4d)); + + assert(!(csp4d < sp2d)); + assert(!(csp4s < sp2s)); + assert(!(csp4d < sp2s)); + assert(!(csp4s < sp2d)); + +// More cross-type comparisons (int vs float) + static_assert(std::span{fArr1, 8} < std::span{iArr1, 9}, ""); + static_assert(std::span{iArr1, 8} < std::span{fArr1, 9}, ""); + assert(!(std::span{fArr2} < std::span{iArr2})); + assert(!(std::span{iArr2} < std::span{fArr2})); + + static_assert(!(std::span{iArr1, 9} < std::span{fArr1, 8}), ""); +} \ No newline at end of file diff --git a/test/std/containers/views/span.comparison/op.ne.pass.cpp b/test/std/containers/views/span.comparison/op.ne.pass.cpp new file mode 100644 index 000000000..ecf05b317 --- /dev/null +++ b/test/std/containers/views/span.comparison/op.ne.pass.cpp @@ -0,0 +1,168 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr bool operator!=(span l, span r); +// +// +// Effects: Equivalent to: return !(l == r); +// + +#include +#include + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span csp0d{}; + constexpr std::span csp1d{iArr1, 10}; + constexpr std::span csp2d{iArr1 + 3, 2}; + constexpr std::span csp3d{iArr1 + 1, 2}; + constexpr std::span csp4d{iArr1 + 6, 2}; + + constexpr std::span csp0s{}; + constexpr std::span csp1s{iArr1, 10}; + constexpr std::span csp2s{iArr1 + 3, 2}; + constexpr std::span csp3s{iArr1 + 1, 2}; + constexpr std::span csp4s{iArr1 + 6, 2}; + + static_assert(!(csp0d != csp0d), ""); + static_assert(!(csp0s != csp0s), ""); + static_assert(!(csp0s != csp0d), ""); + static_assert(!(csp0d != csp0s), ""); + + static_assert( (csp0d != csp1d), ""); + static_assert( (csp0s != csp1s), ""); + static_assert( (csp0s != csp1d), ""); + static_assert( (csp0d != csp1s), ""); + + static_assert(!(csp1d != csp1s), ""); + static_assert(!(csp1s != csp1d), ""); + + static_assert(!(csp2d != csp3d), ""); + static_assert(!(csp2s != csp3s), ""); + static_assert(!(csp2d != csp3s), ""); + static_assert(!(csp2s != csp3d), ""); + + static_assert(!(csp2d != csp3d), ""); + static_assert(!(csp2s != csp3s), ""); + static_assert(!(csp2d != csp3s), ""); + static_assert(!(csp2s != csp3d), ""); + + static_assert( (csp2d != csp4d), ""); + static_assert( (csp2s != csp4s), ""); + static_assert( (csp2d != csp4s), ""); + static_assert( (csp2s != csp4d), ""); + + static_assert( (csp4d != csp2d), ""); + static_assert( (csp4s != csp2s), ""); + static_assert( (csp4d != csp2s), ""); + static_assert( (csp4s != csp2d), ""); + + std::span sp0d{}; + std::span sp1d{iArr2, 10}; + std::span sp2d{iArr2 + 3, 2}; + std::span sp3d{iArr2 + 1, 2}; + std::span sp4d{iArr2 + 6, 2}; + + std::span sp0s{}; + std::span sp1s{iArr2, 10}; + std::span sp2s{iArr2 + 3, 2}; + std::span sp3s{iArr2 + 1, 2}; + std::span sp4s{iArr2 + 6, 2}; + + assert(!(sp0d != sp0d)); + assert(!(sp0s != sp0s)); + assert(!(sp0s != sp0d)); + assert(!(sp0d != sp0s)); + + assert( (sp0d != sp1d)); + assert( (sp0s != sp1s)); + assert( (sp0s != sp1d)); + assert( (sp0d != sp1s)); + + assert(!(sp1d != sp1s)); + assert(!(sp1s != sp1d)); + + assert(!(sp2d != sp3d)); + assert(!(sp2s != sp3s)); + assert(!(sp2d != sp3s)); + assert(!(sp2s != sp3d)); + + assert(!(sp2d != sp3d)); + assert(!(sp2s != sp3s)); + assert(!(sp2d != sp3s)); + assert(!(sp2s != sp3d)); + + assert( (sp2d != sp4d)); + assert( (sp2s != sp4s)); + assert( (sp2d != sp4s)); + assert( (sp2s != sp4d)); + + assert( (sp4d != sp2d)); + assert( (sp4s != sp2s)); + assert( (sp4d != sp2s)); + assert( (sp4s != sp2d)); + +// cross type comparisons + assert(!(csp0d != sp0d)); + assert(!(csp0s != sp0s)); + assert(!(csp0s != sp0d)); + assert(!(csp0d != sp0s)); + + assert( (csp0d != sp1d)); + assert( (csp0s != sp1s)); + assert( (csp0s != sp1d)); + assert( (csp0d != sp1s)); + + assert(!(csp1d != sp1s)); + assert(!(csp1s != sp1d)); + + assert(!(csp2d != sp3d)); + assert(!(csp2s != sp3s)); + assert(!(csp2d != sp3s)); + assert(!(csp2s != sp3d)); + + assert(!(csp2d != sp3d)); + assert(!(csp2s != sp3s)); + assert(!(csp2d != sp3s)); + assert(!(csp2s != sp3d)); + + assert( (csp2d != sp4d)); + assert( (csp2s != sp4s)); + assert( (csp2d != sp4s)); + assert( (csp2s != sp4d)); + + assert( (csp4d != sp2d)); + assert( (csp4s != sp2s)); + assert( (csp4d != sp2s)); + assert( (csp4s != sp2d)); + +// More cross-type comparisons (int vs float) + static_assert(!(std::span{fArr1} != std::span{iArr1}), ""); + static_assert(!(std::span{iArr1} != std::span{fArr1}), ""); + assert(!(std::span{fArr2} != std::span{iArr2})); + assert(!(std::span{iArr2} != std::span{fArr2})); + + static_assert( (std::span{iArr1, 9} != std::span{fArr1, 8}), ""); +} \ No newline at end of file diff --git a/test/std/containers/views/span.cons/array.fail.cpp b/test/std/containers/views/span.cons/array.fail.cpp new file mode 100644 index 000000000..7ef49fc47 --- /dev/null +++ b/test/std/containers/views/span.cons/array.fail.cpp @@ -0,0 +1,72 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr span(element_type (&arr)[N]) noexcept; +// template +// constexpr span(array& arr) noexcept; +// template +// constexpr span(const array& arr) noexcept; +// +// Remarks: These constructors shall not participate in overload resolution unless: +// — extent == dynamic_extent || N == extent is true, and +// — remove_pointer_t(*)[] is convertible to ElementType(*)[]. +// + + +#include +#include +#include + +#include "test_macros.h" + + int arr[] = {1,2,3}; +const int carr[] = {4,5,6}; + volatile int varr[] = {7,8,9}; +const volatile int cvarr[] = {1,3,5}; + +int main () +{ +// Size wrong + { + std::span s1(arr); // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// Type wrong + { + std::span s1(arr); // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s2(arr); // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// CV wrong (dynamically sized) + { + std::span< int> s1{ carr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s2{ varr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s3{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s4{ varr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int> s6{ carr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int> s7{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// CV wrong (statically sized) + { + std::span< int,3> s1{ carr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int,3> s2{ varr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int,3> s3{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s4{ varr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int,3> s6{ carr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int,3> s7{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } +} diff --git a/test/std/containers/views/span.cons/array.pass.cpp b/test/std/containers/views/span.cons/array.pass.cpp new file mode 100644 index 000000000..80a0f07f6 --- /dev/null +++ b/test/std/containers/views/span.cons/array.pass.cpp @@ -0,0 +1,123 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr span(element_type (&arr)[N]) noexcept; +// +// Remarks: These constructors shall not participate in overload resolution unless: +// — extent == dynamic_extent || N == extent is true, and +// — remove_pointer_t(*)[] is convertible to ElementType(*)[]. +// + + +#include +#include +#include + +#include "test_macros.h" + + +void checkCV() +{ + int arr[] = {1,2,3}; + const int carr[] = {4,5,6}; + volatile int varr[] = {7,8,9}; + const volatile int cvarr[] = {1,3,5}; + +// Types the same (dynamic sized) + { + std::span< int> s1{ arr}; // a span< int> pointing at int. + std::span s2{ carr}; // a span pointing at const int. + std::span< volatile int> s3{ varr}; // a span< volatile int> pointing at volatile int. + std::span s4{cvarr}; // a span pointing at const volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 12); + } + +// Types the same (static sized) + { + std::span< int,3> s1{ arr}; // a span< int> pointing at int. + std::span s2{ carr}; // a span pointing at const int. + std::span< volatile int,3> s3{ varr}; // a span< volatile int> pointing at volatile int. + std::span s4{cvarr}; // a span pointing at const volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 12); + } + + +// types different (dynamic sized) + { + std::span s1{ arr}; // a span pointing at int. + std::span< volatile int> s2{ arr}; // a span< volatile int> pointing at int. + std::span< volatile int> s3{ arr}; // a span< volatile int> pointing at const int. + std::span s4{ arr}; // a span pointing at int. + std::span s5{carr}; // a span pointing at const int. + std::span s6{varr}; // a span pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18); + } + +// types different (static sized) + { + std::span s1{ arr}; // a span pointing at int. + std::span< volatile int,3> s2{ arr}; // a span< volatile int> pointing at int. + std::span< volatile int,3> s3{ arr}; // a span< volatile int> pointing at const int. + std::span s4{ arr}; // a span pointing at int. + std::span s5{carr}; // a span pointing at const int. + std::span s6{varr}; // a span pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18); + } +} + + +template +constexpr bool testConstexprSpan() +{ + constexpr T val[2] = {}; + + ASSERT_NOEXCEPT(std::span {val}); + ASSERT_NOEXCEPT(std::span{val}); + std::span s1{val}; + std::span s2{val}; + return + s1.data() == &val[0] && s1.size() == 2 + && s2.data() == &val[0] && s2.size() == 2; +} + + +template +void testRuntimeSpan() +{ + T val[2] = {}; + ASSERT_NOEXCEPT(std::span {val}); + ASSERT_NOEXCEPT(std::span{val}); + std::span s1{val}; + std::span s2{val}; + assert(s1.data() == &val[0] && s1.size() == 2); + assert(s2.data() == &val[0] && s2.size() == 2); +} + +struct A{}; + +int main () +{ + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + + checkCV(); +} diff --git a/test/std/containers/views/span.cons/assign.pass.cpp b/test/std/containers/views/span.cons/assign.pass.cpp new file mode 100644 index 000000000..b5bd7ae00 --- /dev/null +++ b/test/std/containers/views/span.cons/assign.pass.cpp @@ -0,0 +1,293 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr span& operator=(const span& other) noexcept = default; + +#include +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool doAssign(T lhs, T rhs) +{ + ASSERT_NOEXCEPT(std::declval() = rhs); + lhs = rhs; + return lhs.data() == rhs.data() + && lhs.size() == rhs.size(); +} + +struct A{}; + +constexpr int carr1[] = {1,2,3,4}; +constexpr int carr2[] = {3,4,5}; +constexpr int carr3[] = {7,8}; + int arr[] = {5,6,7,9}; +std::string strs[] = {"ABC", "DEF", "GHI"}; + + +int main () +{ + +// constexpr dynamically sized assignment + { +// On systems where 'ptrdiff_t' is a synonym for 'int', +// the call span(ptr, 0) selects the (pointer, index_type) constructor. +// On systems where 'ptrdiff_t' is NOT a synonym for 'int', +// it is ambiguous, because of 0 also being convertible to a null pointer +// and so the compiler can't choose between: +// span(pointer, index_type) +// and span(pointer, pointer) +// We cast zero to std::ptrdiff_t to remove that ambiguity. +// Example: +// On darwin x86_64, ptrdiff_t is the same as long int. +// On darwin i386, ptrdiff_t is the same as int. + constexpr std::span spans[] = { + {}, + {carr1, static_cast(0)}, + {carr1, 1}, + {carr1, 2}, + {carr1, 3}, + {carr1, 4}, + {carr2, static_cast(0)}, + {carr2, 1}, + {carr2, 2}, + {carr2, 3}, + {carr3, static_cast(0)}, + {carr3, 1}, + {carr3, 2} + }; + + static_assert(std::size(spans) == 13, "" ); + +// No for loops in constexpr land :-( + static_assert(doAssign(spans[0], spans[0]), ""); + static_assert(doAssign(spans[0], spans[1]), ""); + static_assert(doAssign(spans[0], spans[2]), ""); + static_assert(doAssign(spans[0], spans[3]), ""); + static_assert(doAssign(spans[0], spans[4]), ""); + static_assert(doAssign(spans[0], spans[5]), ""); + static_assert(doAssign(spans[0], spans[6]), ""); + static_assert(doAssign(spans[0], spans[7]), ""); + static_assert(doAssign(spans[0], spans[8]), ""); + static_assert(doAssign(spans[0], spans[9]), ""); + static_assert(doAssign(spans[0], spans[10]), ""); + static_assert(doAssign(spans[0], spans[11]), ""); + static_assert(doAssign(spans[0], spans[12]), ""); + + static_assert(doAssign(spans[1], spans[1]), ""); + static_assert(doAssign(spans[1], spans[2]), ""); + static_assert(doAssign(spans[1], spans[3]), ""); + static_assert(doAssign(spans[1], spans[4]), ""); + static_assert(doAssign(spans[1], spans[5]), ""); + static_assert(doAssign(spans[1], spans[6]), ""); + static_assert(doAssign(spans[1], spans[7]), ""); + static_assert(doAssign(spans[1], spans[8]), ""); + static_assert(doAssign(spans[1], spans[9]), ""); + static_assert(doAssign(spans[1], spans[10]), ""); + static_assert(doAssign(spans[1], spans[11]), ""); + static_assert(doAssign(spans[1], spans[12]), ""); + + static_assert(doAssign(spans[2], spans[2]), ""); + static_assert(doAssign(spans[2], spans[3]), ""); + static_assert(doAssign(spans[2], spans[4]), ""); + static_assert(doAssign(spans[2], spans[5]), ""); + static_assert(doAssign(spans[2], spans[6]), ""); + static_assert(doAssign(spans[2], spans[7]), ""); + static_assert(doAssign(spans[2], spans[8]), ""); + static_assert(doAssign(spans[2], spans[9]), ""); + static_assert(doAssign(spans[2], spans[10]), ""); + static_assert(doAssign(spans[2], spans[11]), ""); + static_assert(doAssign(spans[2], spans[12]), ""); + + static_assert(doAssign(spans[3], spans[3]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[10]), ""); + static_assert(doAssign(spans[3], spans[11]), ""); + static_assert(doAssign(spans[3], spans[12]), ""); + + static_assert(doAssign(spans[4], spans[4]), ""); + static_assert(doAssign(spans[4], spans[5]), ""); + static_assert(doAssign(spans[4], spans[6]), ""); + static_assert(doAssign(spans[4], spans[7]), ""); + static_assert(doAssign(spans[4], spans[8]), ""); + static_assert(doAssign(spans[4], spans[9]), ""); + static_assert(doAssign(spans[4], spans[10]), ""); + static_assert(doAssign(spans[4], spans[11]), ""); + static_assert(doAssign(spans[4], spans[12]), ""); + + static_assert(doAssign(spans[5], spans[5]), ""); + static_assert(doAssign(spans[5], spans[6]), ""); + static_assert(doAssign(spans[5], spans[7]), ""); + static_assert(doAssign(spans[5], spans[8]), ""); + static_assert(doAssign(spans[5], spans[9]), ""); + static_assert(doAssign(spans[5], spans[10]), ""); + static_assert(doAssign(spans[5], spans[11]), ""); + static_assert(doAssign(spans[5], spans[12]), ""); + + static_assert(doAssign(spans[6], spans[6]), ""); + static_assert(doAssign(spans[6], spans[7]), ""); + static_assert(doAssign(spans[6], spans[8]), ""); + static_assert(doAssign(spans[6], spans[9]), ""); + static_assert(doAssign(spans[6], spans[10]), ""); + static_assert(doAssign(spans[6], spans[11]), ""); + static_assert(doAssign(spans[6], spans[12]), ""); + + static_assert(doAssign(spans[7], spans[7]), ""); + static_assert(doAssign(spans[7], spans[8]), ""); + static_assert(doAssign(spans[7], spans[9]), ""); + static_assert(doAssign(spans[7], spans[10]), ""); + static_assert(doAssign(spans[7], spans[11]), ""); + static_assert(doAssign(spans[7], spans[12]), ""); + + static_assert(doAssign(spans[8], spans[8]), ""); + static_assert(doAssign(spans[8], spans[9]), ""); + static_assert(doAssign(spans[8], spans[10]), ""); + static_assert(doAssign(spans[8], spans[11]), ""); + static_assert(doAssign(spans[8], spans[12]), ""); + + static_assert(doAssign(spans[9], spans[9]), ""); + static_assert(doAssign(spans[9], spans[10]), ""); + static_assert(doAssign(spans[9], spans[11]), ""); + static_assert(doAssign(spans[9], spans[12]), ""); + + static_assert(doAssign(spans[10], spans[10]), ""); + static_assert(doAssign(spans[10], spans[11]), ""); + static_assert(doAssign(spans[10], spans[12]), ""); + + static_assert(doAssign(spans[11], spans[11]), ""); + static_assert(doAssign(spans[11], spans[12]), ""); + + static_assert(doAssign(spans[12], spans[12]), ""); + +// for (size_t i = 0; i < std::size(spans); ++i) +// for (size_t j = i; j < std::size(spans); ++j) +// static_assert(doAssign(spans[i], spans[j]), ""); + } + +// constexpr statically sized assignment + { + constexpr std::span spans[] = { + {carr1, 2}, + {carr1 + 1, 2}, + {carr1 + 2, 2}, + {carr2, 2}, + {carr2 + 1, 2}, + {carr3, 2} + }; + + static_assert(std::size(spans) == 6, "" ); + +// No for loops in constexpr land :-( + static_assert(doAssign(spans[0], spans[0]), ""); + static_assert(doAssign(spans[0], spans[1]), ""); + static_assert(doAssign(spans[0], spans[2]), ""); + static_assert(doAssign(spans[0], spans[3]), ""); + static_assert(doAssign(spans[0], spans[4]), ""); + static_assert(doAssign(spans[0], spans[5]), ""); + + static_assert(doAssign(spans[1], spans[1]), ""); + static_assert(doAssign(spans[1], spans[2]), ""); + static_assert(doAssign(spans[1], spans[3]), ""); + static_assert(doAssign(spans[1], spans[4]), ""); + static_assert(doAssign(spans[1], spans[5]), ""); + + static_assert(doAssign(spans[2], spans[2]), ""); + static_assert(doAssign(spans[2], spans[3]), ""); + static_assert(doAssign(spans[2], spans[4]), ""); + static_assert(doAssign(spans[2], spans[5]), ""); + + static_assert(doAssign(spans[3], spans[3]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[5]), ""); + + static_assert(doAssign(spans[4], spans[4]), ""); + static_assert(doAssign(spans[4], spans[5]), ""); + + static_assert(doAssign(spans[5], spans[5]), ""); + +// for (size_t i = 0; i < std::size(spans); ++i) +// for (size_t j = i; j < std::size(spans); ++j) +// static_assert(doAssign(spans[i], spans[j]), ""); + } + + +// dynamically sized assignment + { + std::span spans[] = { + {}, + {arr, arr + 1}, + {arr, arr + 2}, + {arr, arr + 3}, + {arr + 1, arr + 3} // same size as s2 + }; + + for (size_t i = 0; i < std::size(spans); ++i) + for (size_t j = i; j < std::size(spans); ++j) + assert((doAssign(spans[i], spans[j]))); + } + +// statically sized assignment + { + std::span spans[] = { + {arr, arr + 2}, + {arr + 1, arr + 3}, + {arr + 2, arr + 4} + }; + + for (size_t i = 0; i < std::size(spans); ++i) + for (size_t j = i; j < std::size(spans); ++j) + assert((doAssign(spans[i], spans[j]))); + } + +// dynamically sized assignment + { + std::span spans[] = { + {strs, strs}, + {strs, strs + 1}, + {strs, strs + 2}, + {strs, strs + 3}, + {strs + 1, strs + 1}, + {strs + 1, strs + 2}, + {strs + 1, strs + 3}, + {strs + 2, strs + 2}, + {strs + 2, strs + 3}, + {strs + 3, strs + 3} + }; + + for (size_t i = 0; i < std::size(spans); ++i) + for (size_t j = i; j < std::size(spans); ++j) + assert((doAssign(spans[i], spans[j]))); + } + + { + std::span spans[] = { + {strs, strs + 1}, + {strs + 1, strs + 2}, + {strs + 2, strs + 3} + }; + + for (size_t i = 0; i < std::size(spans); ++i) + for (size_t j = i; j < std::size(spans); ++j) + assert((doAssign(spans[i], spans[j]))); + } +} diff --git a/test/std/containers/views/span.cons/container.fail.cpp b/test/std/containers/views/span.cons/container.fail.cpp new file mode 100644 index 000000000..ecd7fcb91 --- /dev/null +++ b/test/std/containers/views/span.cons/container.fail.cpp @@ -0,0 +1,117 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr span(Container& cont); +// template +// constexpr span(const Container& cont); +// +// Remarks: These constructors shall not participate in overload resolution unless: +// — Container is not a specialization of span, +// — Container is not a specialization of array, +// — is_array_v is false, +// — data(cont) and size(cont) are both well-formed, and +// — remove_pointer_t(*)[] is convertible to ElementType(*)[]. +// + + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// Look ma - I'm a container! +template +struct IsAContainer { + constexpr IsAContainer() : v_{} {} + constexpr size_t size() const {return 1;} + constexpr T *data() {return &v_;} + constexpr const T *data() const {return &v_;} + + constexpr const T *getV() const {return &v_;} // for checking + T v_; +}; + +template +struct NotAContainerNoData { + size_t size() const {return 0;} +}; + +template +struct NotAContainerNoSize { + const T *data() const {return nullptr;} +}; + +template +struct NotAContainerPrivate { +private: + size_t size() const {return 0;} + const T *data() const {return nullptr;} +}; + + +int main () +{ + +// Missing size and/or data + { + std::span s1{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s2{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s3{NotAContainerNoData()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s4{NotAContainerNoData()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{NotAContainerNoSize()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s6{NotAContainerNoSize()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s7{NotAContainerPrivate()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s8{NotAContainerPrivate()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + +// Again with the standard containers + std::span s11{std::deque()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s12{std::deque()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s13{std::list()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s14{std::list()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s15{std::forward_list()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s16{std::forward_list()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// Not the same type + { + std::span s1{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s2{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// CV wrong (dynamically sized) + { + std::span< int> s1{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s2{IsAContainer< volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s3{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s4{IsAContainer< volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int> s6{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int> s7{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// CV wrong (statically sized) + { + std::span< int,1> s1{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int,1> s2{IsAContainer< volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int,1> s3{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s4{IsAContainer< volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int,1> s6{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int,1> s7{IsAContainer()}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +} diff --git a/test/std/containers/views/span.cons/container.pass.cpp b/test/std/containers/views/span.cons/container.pass.cpp new file mode 100644 index 000000000..478a3dac5 --- /dev/null +++ b/test/std/containers/views/span.cons/container.pass.cpp @@ -0,0 +1,118 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr span(Container& cont); +// template +// constexpr span(const Container& cont); +// +// Remarks: These constructors shall not participate in overload resolution unless: +// — Container is not a specialization of span, +// — Container is not a specialization of array, +// — is_array_v is false, +// — data(cont) and size(cont) are both well-formed, and +// — remove_pointer_t(*)[] is convertible to ElementType(*)[]. +// + + +#include +#include +#include +#include + +#include "test_macros.h" + +// Look ma - I'm a container! +template +struct IsAContainer { + constexpr IsAContainer() : v_{} {} + constexpr size_t size() const {return 1;} + constexpr T *data() {return &v_;} + constexpr const T *data() const {return &v_;} + + constexpr T const *getV() const {return &v_;} // for checking + T v_; +}; + + +void checkCV() +{ + std::vector v = {1,2,3}; + +// Types the same (dynamic sized) + { + std::span< int> s1{v}; // a span< int> pointing at int. + } + +// Types the same (static sized) + { + std::span< int,3> s1{v}; // a span< int> pointing at int. + } + +// types different (dynamic sized) + { + std::span s1{v}; // a span pointing at int. + std::span< volatile int> s2{v}; // a span< volatile int> pointing at int. + std::span< volatile int> s3{v}; // a span< volatile int> pointing at const int. + std::span s4{v}; // a span pointing at int. + } + +// types different (static sized) + { + std::span s1{v}; // a span pointing at int. + std::span< volatile int,3> s2{v}; // a span< volatile int> pointing at int. + std::span< volatile int,3> s3{v}; // a span< volatile int> pointing at const int. + std::span s4{v}; // a span pointing at int. + } +} + + +template +constexpr bool testConstexprSpan() +{ + constexpr IsAContainer val{}; + std::span s1{val}; + std::span s2{val}; + return + s1.data() == val.getV() && s1.size() == 1 + && s2.data() == val.getV() && s2.size() == 1; +} + + +template +void testRuntimeSpan() +{ + IsAContainer val{}; + std::span s1{val}; + std::span s2{val}; + assert(s1.data() == val.getV() && s1.size() == 1); + assert(s2.data() == val.getV() && s2.size() == 1); +} + +struct A{}; + +int main () +{ + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + + checkCV(); +} diff --git a/test/std/containers/views/span.cons/copy.pass.cpp b/test/std/containers/views/span.cons/copy.pass.cpp new file mode 100644 index 000000000..2cfffbbd4 --- /dev/null +++ b/test/std/containers/views/span.cons/copy.pass.cpp @@ -0,0 +1,71 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr span(const span& other) noexcept = default; + +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool doCopy(const T &rhs) +{ + ASSERT_NOEXCEPT(T{rhs}); + T lhs{rhs}; + return lhs.data() == rhs.data() + && lhs.size() == rhs.size(); +} + +struct A{}; + +template +void testCV () +{ + int arr[] = {1,2,3}; + assert((doCopy(std::span () ))); + assert((doCopy(std::span() ))); + assert((doCopy(std::span (&arr[0], 1)))); + assert((doCopy(std::span(&arr[0], 1)))); + assert((doCopy(std::span (&arr[0], 2)))); + assert((doCopy(std::span(&arr[0], 2)))); +} + + +int main () +{ + constexpr int carr[] = {1,2,3}; + + static_assert(doCopy(std::span< int> ()), ""); + static_assert(doCopy(std::span< int,0>()), ""); + static_assert(doCopy(std::span (&carr[0], 1)), ""); + static_assert(doCopy(std::span(&carr[0], 1)), ""); + static_assert(doCopy(std::span (&carr[0], 2)), ""); + static_assert(doCopy(std::span(&carr[0], 2)), ""); + + static_assert(doCopy(std::span()), ""); + static_assert(doCopy(std::span()), ""); + static_assert(doCopy(std::span()), ""); + + std::string s; + assert(doCopy(std::span () )); + assert(doCopy(std::span() )); + assert(doCopy(std::span (&s, 1))); + assert(doCopy(std::span(&s, 1))); + + testCV< int>(); + testCV(); + testCV< volatile int>(); + testCV(); +} diff --git a/test/std/containers/views/span.cons/deduct.pass.cpp b/test/std/containers/views/span.cons/deduct.pass.cpp new file mode 100644 index 000000000..3410bb31c --- /dev/null +++ b/test/std/containers/views/span.cons/deduct.pass.cpp @@ -0,0 +1,83 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// span(T (&)[N]) -> span; +// +// template +// span(array&) -> span; +// +// template +// span(const array&) -> span; +// +// template +// span(Container&) -> span; +// +// template +// span(const Container&) -> span; + + + +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +int main () +{ + { + int arr[] = {1,2,3}; + std::span s{arr}; + using S = decltype(s); + ASSERT_SAME_TYPE(S, std::span); + assert((std::equal(std::begin(arr), std::end(arr), s.begin(), s.end()))); + } + + { + std::array arr = {1.0, 2.0, 3.0, 4.0}; + std::span s{arr}; + using S = decltype(s); + ASSERT_SAME_TYPE(S, std::span); + assert((std::equal(std::begin(arr), std::end(arr), s.begin(), s.end()))); + } + + { + const std::array arr = {4, 5, 6, 7, 8}; + std::span s{arr}; + using S = decltype(s); + ASSERT_SAME_TYPE(S, std::span); + assert((std::equal(std::begin(arr), std::end(arr), s.begin(), s.end()))); + } + + { + std::string str{"ABCDE"}; + std::span s{str}; + using S = decltype(s); + ASSERT_SAME_TYPE(S, std::span); + assert((size_t)s.size() == str.size()); + assert((std::equal(s.begin(), s.end(), std::begin(s), std::end(s)))); + } + + { + const std::string str{"QWERTYUIOP"}; + std::span s{str}; + using S = decltype(s); + ASSERT_SAME_TYPE(S, std::span); + assert((size_t)s.size() == str.size()); + assert((std::equal(s.begin(), s.end(), std::begin(s), std::end(s)))); + } +} diff --git a/test/std/containers/views/span.cons/default.fail.cpp b/test/std/containers/views/span.cons/default.fail.cpp new file mode 100644 index 000000000..d1fefe5b3 --- /dev/null +++ b/test/std/containers/views/span.cons/default.fail.cpp @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr span() noexcept; +// +// Remarks: This constructor shall not participate in overload resolution +// unless Extent <= 0 is true. + + +#include +#include +#include + +#include "test_macros.h" + +int main () +{ + std::span s; // expected-error@span:* {{static_assert failed "Can't default construct a statically sized span with size > 0"}} + +// TODO: This is what I want: +// eXpected-error {{no matching constructor for initialization of 'std::span'}} +} diff --git a/test/std/containers/views/span.cons/default.pass.cpp b/test/std/containers/views/span.cons/default.pass.cpp new file mode 100644 index 000000000..f7e496696 --- /dev/null +++ b/test/std/containers/views/span.cons/default.pass.cpp @@ -0,0 +1,82 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr span() noexcept; + +#include +#include +#include + +#include "test_macros.h" + +void checkCV() +{ +// Types the same (dynamic sized) + { + std::span< int> s1; + std::span s2; + std::span< volatile int> s3; + std::span s4; + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } + +// Types the same (static sized) + { + std::span< int,0> s1; + std::span s2; + std::span< volatile int,0> s3; + std::span s4; + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } +} + + +template +constexpr bool testConstexprSpan() +{ + std::span s1; + std::span s2; + return + s1.data() == nullptr && s1.size() == 0 + && s2.data() == nullptr && s2.size() == 0; +} + + +template +void testRuntimeSpan() +{ + ASSERT_NOEXCEPT(T{}); + std::span s1; + std::span s2; + assert(s1.data() == nullptr && s1.size() == 0); + assert(s2.data() == nullptr && s2.size() == 0); +} + + +struct A{}; + +int main () +{ + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + + checkCV(); +} diff --git a/test/std/containers/views/span.cons/ptr_len.fail.cpp b/test/std/containers/views/span.cons/ptr_len.fail.cpp new file mode 100644 index 000000000..db24e3d26 --- /dev/null +++ b/test/std/containers/views/span.cons/ptr_len.fail.cpp @@ -0,0 +1,63 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr span(pointer ptr, index_type count); +// Requires: [ptr, ptr + count) shall be a valid range. +// If extent is not equal to dynamic_extent, then count shall be equal to extent. +// + +#include +#include +#include + +#include "test_macros.h" + + + int arr[] = {1,2,3}; +const int carr[] = {4,5,6}; + volatile int varr[] = {7,8,9}; +const volatile int cvarr[] = {1,3,5}; + +int main () +{ +// We can't check that the size doesn't match - because that's a runtime property +// std::span s1(arr, 3); + +// Type wrong + { + std::span s1(arr, 3); // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s2(arr, 3); // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// CV wrong (dynamically sized) + { + std::span< int> s1{ carr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s2{ varr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s3{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s4{ varr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int> s6{ carr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int> s7{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// CV wrong (statically sized) + { + std::span< int,3> s1{ carr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int,3> s2{ varr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int,3> s3{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s4{ varr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int,3> s6{ carr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int,3> s7{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } +} diff --git a/test/std/containers/views/span.cons/ptr_len.pass.cpp b/test/std/containers/views/span.cons/ptr_len.pass.cpp new file mode 100644 index 000000000..7302759bc --- /dev/null +++ b/test/std/containers/views/span.cons/ptr_len.pass.cpp @@ -0,0 +1,113 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr span(pointer ptr, index_type count); +// Requires: [ptr, ptr + count) shall be a valid range. +// If extent is not equal to dynamic_extent, then count shall be equal to extent. +// + +#include +#include +#include + +#include "test_macros.h" + +void checkCV() +{ + int arr[] = {1,2,3}; + const int carr[] = {4,5,6}; + volatile int varr[] = {7,8,9}; + const volatile int cvarr[] = {1,3,5}; + +// Types the same (dynamic sized) + { + std::span< int> s1{ arr, 3}; // a span< int> pointing at int. + std::span s2{ carr, 3}; // a span pointing at const int. + std::span< volatile int> s3{ varr, 3}; // a span< volatile int> pointing at volatile int. + std::span s4{cvarr, 3}; // a span pointing at const volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 12); + } + +// Types the same (static sized) + { + std::span< int,3> s1{ arr, 3}; // a span< int> pointing at int. + std::span s2{ carr, 3}; // a span pointing at const int. + std::span< volatile int,3> s3{ varr, 3}; // a span< volatile int> pointing at volatile int. + std::span s4{cvarr, 3}; // a span pointing at const volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 12); + } + + +// types different (dynamic sized) + { + std::span s1{ arr, 3}; // a span pointing at int. + std::span< volatile int> s2{ arr, 3}; // a span< volatile int> pointing at int. + std::span< volatile int> s3{ arr, 3}; // a span< volatile int> pointing at const int. + std::span s4{ arr, 3}; // a span pointing at int. + std::span s5{carr, 3}; // a span pointing at const int. + std::span s6{varr, 3}; // a span pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18); + } + +// types different (static sized) + { + std::span s1{ arr, 3}; // a span pointing at int. + std::span< volatile int,3> s2{ arr, 3}; // a span< volatile int> pointing at int. + std::span< volatile int,3> s3{ arr, 3}; // a span< volatile int> pointing at const int. + std::span s4{ arr, 3}; // a span pointing at int. + std::span s5{carr, 3}; // a span pointing at const int. + std::span s6{varr, 3}; // a span pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18); + } +} + + +template +constexpr bool testConstexprSpan() +{ + constexpr T val[2] = {}; + std::span s1{val, 2}; + std::span s2{val, 2}; + return + s1.data() == &val[0] && s1.size() == 2 + && s2.data() == &val[0] && s2.size() == 2; +} + + +template +void testRuntimeSpan() +{ + T val[2] = {}; + std::span s1{val, 2}; + std::span s2{val, 2}; + assert(s1.data() == &val[0] && s1.size() == 2); + assert(s2.data() == &val[0] && s2.size() == 2); +} + +struct A{}; + +int main () +{ + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + + checkCV(); +} diff --git a/test/std/containers/views/span.cons/ptr_ptr.fail.cpp b/test/std/containers/views/span.cons/ptr_ptr.fail.cpp new file mode 100644 index 000000000..a55f0592a --- /dev/null +++ b/test/std/containers/views/span.cons/ptr_ptr.fail.cpp @@ -0,0 +1,63 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr span(pointer first, pointer last); +// Requires: [first, last) shall be a valid range. +// If extent is not equal to dynamic_extent, then last - first shall be equal to extent. +// + +#include +#include +#include + +#include "test_macros.h" + + + int arr[] = {1,2,3}; +const int carr[] = {4,5,6}; + volatile int varr[] = {7,8,9}; +const volatile int cvarr[] = {1,3,5}; + +int main () +{ +// We can't check that the size doesn't match - because that's a runtime property +// std::span s1(arr, arr + 3); + +// Type wrong + { + std::span s1(arr, arr + 3); // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s2(arr, arr + 3); // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// CV wrong (dynamically sized) + { + std::span< int> s1{ carr, carr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s2{ varr, varr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s3{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s4{ varr, varr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int> s6{ carr, carr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int> s7{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// CV wrong (statically sized) + { + std::span< int,3> s1{ carr, carr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int,3> s2{ varr, varr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int,3> s3{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s4{ varr, varr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int,3> s6{ carr, carr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int,3> s7{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } +} diff --git a/test/std/containers/views/span.cons/ptr_ptr.pass.cpp b/test/std/containers/views/span.cons/ptr_ptr.pass.cpp new file mode 100644 index 000000000..afb525e73 --- /dev/null +++ b/test/std/containers/views/span.cons/ptr_ptr.pass.cpp @@ -0,0 +1,113 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr span(pointer first, pointer last); +// Requires: [first, last) shall be a valid range. +// If extent is not equal to dynamic_extent, then last - first shall be equal to extent. +// + +#include +#include +#include + +#include "test_macros.h" + +void checkCV() +{ + int arr[] = {1,2,3}; + const int carr[] = {4,5,6}; + volatile int varr[] = {7,8,9}; + const volatile int cvarr[] = {1,3,5}; + +// Types the same (dynamic sized) + { + std::span< int> s1{ arr, arr + 3}; // a span< int> pointing at int. + std::span s2{ carr, carr + 3}; // a span pointing at const int. + std::span< volatile int> s3{ varr, varr + 3}; // a span< volatile int> pointing at volatile int. + std::span s4{cvarr, cvarr + 3}; // a span pointing at const volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 12); + } + +// Types the same (static sized) + { + std::span< int,3> s1{ arr, arr + 3}; // a span< int> pointing at int. + std::span s2{ carr, carr + 3}; // a span pointing at const int. + std::span< volatile int,3> s3{ varr, varr + 3}; // a span< volatile int> pointing at volatile int. + std::span s4{cvarr, cvarr + 3}; // a span pointing at const volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 12); + } + + +// types different (dynamic sized) + { + std::span s1{ arr, arr + 3}; // a span pointing at int. + std::span< volatile int> s2{ arr, arr + 3}; // a span< volatile int> pointing at int. + std::span< volatile int> s3{ arr, arr + 3}; // a span< volatile int> pointing at const int. + std::span s4{ arr, arr + 3}; // a span pointing at int. + std::span s5{carr, carr + 3}; // a span pointing at const int. + std::span s6{varr, varr + 3}; // a span pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18); + } + +// types different (static sized) + { + std::span s1{ arr, arr + 3}; // a span pointing at int. + std::span< volatile int,3> s2{ arr, arr + 3}; // a span< volatile int> pointing at int. + std::span< volatile int,3> s3{ arr, arr + 3}; // a span< volatile int> pointing at const int. + std::span s4{ arr, arr + 3}; // a span pointing at int. + std::span s5{carr, carr + 3}; // a span pointing at const int. + std::span s6{varr, varr + 3}; // a span pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18); + } +} + + +template +constexpr bool testConstexprSpan() +{ + constexpr T val[2] = {}; + std::span s1{val, val+2}; + std::span s2{val, val+2}; + return + s1.data() == &val[0] && s1.size() == 2 + && s2.data() == &val[0] && s2.size() == 2; +} + + +template +void testRuntimeSpan() +{ + T val[2] = {}; + std::span s1{val, val+2}; + std::span s2{val, val+2}; + assert(s1.data() == &val[0] && s1.size() == 2); + assert(s2.data() == &val[0] && s2.size() == 2); +} + +struct A{}; + +int main () +{ + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + + checkCV(); +} diff --git a/test/std/containers/views/span.cons/span.fail.cpp b/test/std/containers/views/span.cons/span.fail.cpp new file mode 100644 index 000000000..1fa71551b --- /dev/null +++ b/test/std/containers/views/span.cons/span.fail.cpp @@ -0,0 +1,104 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr span(const span& s) noexcept; +// +// Remarks: This constructor shall not participate in overload resolution unless: +// Extent == dynamic_extent || Extent == OtherExtent is true, and +// OtherElementType(*)[] is convertible to ElementType(*)[]. + + +#include +#include +#include + +#include "test_macros.h" + +void checkCV () +{ +// std::span< int> sp; + std::span csp; + std::span< volatile int> vsp; + std::span cvsp; + +// std::span< int, 0> sp0; + std::span csp0; + std::span< volatile int, 0> vsp0; + std::span cvsp0; + +// Try to remove const and/or volatile (dynamic -> dynamic) + { + std::span< int> s1{ csp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s2{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s3{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + + std::span s4{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + + std::span< volatile int> s6{ csp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int> s7{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// Try to remove const and/or volatile (static -> static) + { + std::span< int, 0> s1{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int, 0> s2{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int, 0> s3{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + + std::span s4{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + + std::span< volatile int, 0> s6{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int, 0> s7{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// Try to remove const and/or volatile (static -> dynamic) + { + std::span< int> s1{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s2{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int> s3{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + + std::span s4{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + + std::span< volatile int> s6{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int> s7{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } + +// Try to remove const and/or volatile (static -> static) + { + std::span< int, 0> s1{ csp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int, 0> s2{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< int, 0> s3{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + + std::span s4{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s5{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + + std::span< volatile int, 0> s6{ csp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span< volatile int, 0> s7{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + } +} + +int main () +{ + std::span sp; + std::span sp0; + + std::span s1{sp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s2{sp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s3{sp}; // expected-error {{no matching constructor for initialization of 'std::span'}} + std::span s4{sp0}; // expected-error {{no matching constructor for initialization of 'std::span'}} + + checkCV(); +} diff --git a/test/std/containers/views/span.cons/span.pass.cpp b/test/std/containers/views/span.cons/span.pass.cpp new file mode 100644 index 000000000..b2024ce12 --- /dev/null +++ b/test/std/containers/views/span.cons/span.pass.cpp @@ -0,0 +1,142 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr span(const span& s) noexcept; +// +// Remarks: This constructor shall not participate in overload resolution unless: +// Extent == dynamic_extent || Extent == OtherExtent is true, and +// OtherElementType(*)[] is convertible to ElementType(*)[]. + + +#include +#include +#include + +#include "test_macros.h" + +void checkCV() +{ + std::span< int> sp; +// std::span csp; + std::span< volatile int> vsp; +// std::span cvsp; + + std::span< int, 0> sp0; +// std::span csp0; + std::span< volatile int, 0> vsp0; +// std::span cvsp0; + +// dynamic -> dynamic + { + std::span s1{ sp}; // a span pointing at int. + std::span< volatile int> s2{ sp}; // a span< volatile int> pointing at int. + std::span s3{ sp}; // a span pointing at int. + std::span s4{ vsp}; // a span pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } + +// static -> static + { + std::span s1{ sp0}; // a span pointing at int. + std::span< volatile int, 0> s2{ sp0}; // a span< volatile int> pointing at int. + std::span s3{ sp0}; // a span pointing at int. + std::span s4{ vsp0}; // a span pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } + +// static -> dynamic + { + std::span s1{ sp0}; // a span pointing at int. + std::span< volatile int> s2{ sp0}; // a span< volatile int> pointing at int. + std::span s3{ sp0}; // a span pointing at int. + std::span s4{ vsp0}; // a span pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } + +// dynamic -> static + { + std::span s1{ sp}; // a span pointing at int. + std::span< volatile int, 0> s2{ sp}; // a span< volatile int> pointing at int. + std::span s3{ sp}; // a span pointing at int. + std::span s4{ vsp}; // a span pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } +} + + +template +constexpr bool testConstexprSpan() +{ + std::span s0{}; + std::span s1(s0); // dynamic -> static + std::span s2(s1); // static -> dynamic + ASSERT_NOEXCEPT(std::span {s0}); + ASSERT_NOEXCEPT(std::span{s1}); + ASSERT_NOEXCEPT(std::span {s1}); + ASSERT_NOEXCEPT(std::span{s0}); + + return + s1.data() == nullptr && s1.size() == 0 + && s2.data() == nullptr && s2.size() == 0; +} + + +template +void testRuntimeSpan() +{ + std::span s0{}; + std::span s1(s0); // dynamic -> static + std::span s2(s1); // static -> dynamic + ASSERT_NOEXCEPT(std::span {s0}); + ASSERT_NOEXCEPT(std::span{s1}); + ASSERT_NOEXCEPT(std::span {s1}); + ASSERT_NOEXCEPT(std::span{s0}); + + assert(s1.data() == nullptr && s1.size() == 0); + assert(s2.data() == nullptr && s2.size() == 0); +} + + +template +bool testConversionSpan() +{ + static_assert(std::is_convertible_v, "Bad input types to 'testConversionSpan"); + std::span s0d{}; + std::span s0s{}; + std::span s1(s0d); // dynamic -> static + std::span s2(s0s); // static -> dynamic + s1.data() == nullptr && s1.size() == 0 + && s2.data() == nullptr && s2.size() == 0; +} + +struct A{}; + +int main () +{ + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + +// TODO: Add some conversion tests here that aren't "X --> const X" +// assert((testConversionSpan())); + + checkCV(); +} diff --git a/test/std/containers/views/span.cons/stdarray.pass.cpp b/test/std/containers/views/span.cons/stdarray.pass.cpp new file mode 100644 index 000000000..204935db0 --- /dev/null +++ b/test/std/containers/views/span.cons/stdarray.pass.cpp @@ -0,0 +1,111 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr span(array& arr) noexcept; +// template +// constexpr span(const array& arr) noexcept; +// +// Remarks: These constructors shall not participate in overload resolution unless: +// — extent == dynamic_extent || N == extent is true, and +// — remove_pointer_t(*)[] is convertible to ElementType(*)[]. +// + + +#include +#include +#include + +#include "test_macros.h" + + +void checkCV() +{ + std::array arr = {1,2,3}; +// STL says these are not cromulent +// std::array carr = {4,5,6}; +// std::array varr = {7,8,9}; +// std::array cvarr = {1,3,5}; + +// Types the same (dynamic sized) + { + std::span< int> s1{ arr}; // a span< int> pointing at int. + } + +// Types the same (static sized) + { + std::span< int,3> s1{ arr}; // a span< int> pointing at int. + } + + +// types different (dynamic sized) + { + std::span s1{ arr}; // a span pointing at int. + std::span< volatile int> s2{ arr}; // a span< volatile int> pointing at int. + std::span< volatile int> s3{ arr}; // a span< volatile int> pointing at const int. + std::span s4{ arr}; // a span pointing at int. + } + +// types different (static sized) + { + std::span s1{ arr}; // a span pointing at int. + std::span< volatile int,3> s2{ arr}; // a span< volatile int> pointing at int. + std::span< volatile int,3> s3{ arr}; // a span< volatile int> pointing at const int. + std::span s4{ arr}; // a span pointing at int. + } +} + + +template +constexpr bool testConstexprSpan() +{ + constexpr std::array val = { T(), T() }; + ASSERT_NOEXCEPT(std::span {val}); + ASSERT_NOEXCEPT(std::span{val}); + std::span s1{val}; + std::span s2{val}; + return + s1.data() == &val[0] && s1.size() == 2 + && s2.data() == &val[0] && s2.size() == 2; +} + + +template +void testRuntimeSpan() +{ + std::array val; + ASSERT_NOEXCEPT(std::span {val}); + ASSERT_NOEXCEPT(std::span{val}); + std::span s1{val}; + std::span s2{val}; + assert(s1.data() == &val[0] && s1.size() == 2); + assert(s2.data() == &val[0] && s2.size() == 2); +} + +struct A{}; + +int main () +{ + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + static_assert(testConstexprSpan(), ""); + + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + testRuntimeSpan(); + + checkCV(); +} diff --git a/test/std/containers/views/span.elem/data.pass.cpp b/test/std/containers/views/span.elem/data.pass.cpp new file mode 100644 index 000000000..3bc6fbbe5 --- /dev/null +++ b/test/std/containers/views/span.elem/data.pass.cpp @@ -0,0 +1,121 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr pointer data() const noexcept; +// + + +#include +#include +#include + +#include "test_macros.h" + + +template +constexpr bool testConstexprSpan(Span sp, typename Span::pointer ptr) +{ + ASSERT_NOEXCEPT(sp.data()); + return sp.data() == ptr; +} + + +template +void testRuntimeSpan(Span sp, typename Span::pointer ptr) +{ + ASSERT_NOEXCEPT(sp.data()); + assert(sp.data() == ptr); +} + +struct A{}; +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +int main () +{ + +// dynamic size + static_assert(testConstexprSpan(std::span(), nullptr), ""); + static_assert(testConstexprSpan(std::span(), nullptr), ""); + static_assert(testConstexprSpan(std::span(), nullptr), ""); + static_assert(testConstexprSpan(std::span(), nullptr), ""); + static_assert(testConstexprSpan(std::span(), nullptr), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 1), iArr1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2), iArr1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3), iArr1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4), iArr1), ""); + + static_assert(testConstexprSpan(std::span(iArr1 + 1, 1), iArr1 + 1), ""); + static_assert(testConstexprSpan(std::span(iArr1 + 2, 2), iArr1 + 2), ""); + static_assert(testConstexprSpan(std::span(iArr1 + 3, 3), iArr1 + 3), ""); + static_assert(testConstexprSpan(std::span(iArr1 + 4, 4), iArr1 + 4), ""); + +// static size + static_assert(testConstexprSpan(std::span(), nullptr), ""); + static_assert(testConstexprSpan(std::span(), nullptr), ""); + static_assert(testConstexprSpan(std::span(), nullptr), ""); + static_assert(testConstexprSpan(std::span(), nullptr), ""); + static_assert(testConstexprSpan(std::span(), nullptr), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 1), iArr1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2), iArr1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3), iArr1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4), iArr1), ""); + + static_assert(testConstexprSpan(std::span(iArr1 + 1, 1), iArr1 + 1), ""); + static_assert(testConstexprSpan(std::span(iArr1 + 2, 2), iArr1 + 2), ""); + static_assert(testConstexprSpan(std::span(iArr1 + 3, 3), iArr1 + 3), ""); + static_assert(testConstexprSpan(std::span(iArr1 + 4, 4), iArr1 + 4), ""); + + +// dynamic size + testRuntimeSpan(std::span(), nullptr); + testRuntimeSpan(std::span(), nullptr); + testRuntimeSpan(std::span(), nullptr); + testRuntimeSpan(std::span(), nullptr); + testRuntimeSpan(std::span(), nullptr); + + testRuntimeSpan(std::span(iArr2, 1), iArr2); + testRuntimeSpan(std::span(iArr2, 2), iArr2); + testRuntimeSpan(std::span(iArr2, 3), iArr2); + testRuntimeSpan(std::span(iArr2, 4), iArr2); + + testRuntimeSpan(std::span(iArr2 + 1, 1), iArr2 + 1); + testRuntimeSpan(std::span(iArr2 + 2, 2), iArr2 + 2); + testRuntimeSpan(std::span(iArr2 + 3, 3), iArr2 + 3); + testRuntimeSpan(std::span(iArr2 + 4, 4), iArr2 + 4); + +// static size + testRuntimeSpan(std::span(), nullptr); + testRuntimeSpan(std::span(), nullptr); + testRuntimeSpan(std::span(), nullptr); + testRuntimeSpan(std::span(), nullptr); + testRuntimeSpan(std::span(), nullptr); + + testRuntimeSpan(std::span(iArr2, 1), iArr2); + testRuntimeSpan(std::span(iArr2, 2), iArr2); + testRuntimeSpan(std::span(iArr2, 3), iArr2); + testRuntimeSpan(std::span(iArr2, 4), iArr2); + + testRuntimeSpan(std::span(iArr2 + 1, 1), iArr2 + 1); + testRuntimeSpan(std::span(iArr2 + 2, 2), iArr2 + 2); + testRuntimeSpan(std::span(iArr2 + 3, 3), iArr2 + 3); + testRuntimeSpan(std::span(iArr2 + 4, 4), iArr2 + 4); + + + std::string s; + testRuntimeSpan(std::span(&s, 1), &s); + testRuntimeSpan(std::span(&s, 1), &s); + +} diff --git a/test/std/containers/views/span.elem/op_idx.pass.cpp b/test/std/containers/views/span.elem/op_idx.pass.cpp new file mode 100644 index 000000000..a88f44104 --- /dev/null +++ b/test/std/containers/views/span.elem/op_idx.pass.cpp @@ -0,0 +1,119 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr reference operator[](index_type idx) const; +// constexpr reference operator()(index_type idx) const; +// + + +#include +#include +#include + +#include "test_macros.h" + + +template +constexpr bool testConstexprSpan(Span sp, ptrdiff_t idx) +{ + _LIBCPP_ASSERT(noexcept(sp[idx]), ""); + _LIBCPP_ASSERT(noexcept(sp(idx)), ""); + + typename Span::reference r1 = sp[idx]; + typename Span::reference r2 = sp(idx); + typename Span::reference r3 = *(sp.data() + idx); + return r1 == r2 && r2 == r3; +} + + +template +void testRuntimeSpan(Span sp, ptrdiff_t idx) +{ + _LIBCPP_ASSERT(noexcept(sp[idx]), ""); + _LIBCPP_ASSERT(noexcept(sp(idx)), ""); + + typename Span::reference r1 = sp[idx]; + typename Span::reference r2 = sp(idx); + typename Span::reference r3 = *(sp.data() + idx); + assert(r1 == r2 && r2 == r3); +} + +struct A{}; +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +int main () +{ + static_assert(testConstexprSpan(std::span(iArr1, 1), 0), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 2), 0), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2), 1), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 3), 0), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3), 1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3), 2), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 4), 0), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4), 1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4), 2), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4), 3), ""); + + + static_assert(testConstexprSpan(std::span(iArr1, 1), 0), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 2), 0), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2), 1), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 3), 0), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3), 1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3), 2), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 4), 0), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4), 1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4), 2), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4), 3), ""); + + + testRuntimeSpan(std::span(iArr2, 1), 0); + + testRuntimeSpan(std::span(iArr2, 2), 0); + testRuntimeSpan(std::span(iArr2, 2), 1); + + testRuntimeSpan(std::span(iArr2, 3), 0); + testRuntimeSpan(std::span(iArr2, 3), 1); + testRuntimeSpan(std::span(iArr2, 3), 2); + + testRuntimeSpan(std::span(iArr2, 4), 0); + testRuntimeSpan(std::span(iArr2, 4), 1); + testRuntimeSpan(std::span(iArr2, 4), 2); + testRuntimeSpan(std::span(iArr2, 4), 3); + + + testRuntimeSpan(std::span(iArr2, 1), 0); + + testRuntimeSpan(std::span(iArr2, 2), 0); + testRuntimeSpan(std::span(iArr2, 2), 1); + + testRuntimeSpan(std::span(iArr2, 3), 0); + testRuntimeSpan(std::span(iArr2, 3), 1); + testRuntimeSpan(std::span(iArr2, 3), 2); + + testRuntimeSpan(std::span(iArr2, 4), 0); + testRuntimeSpan(std::span(iArr2, 4), 1); + testRuntimeSpan(std::span(iArr2, 4), 2); + testRuntimeSpan(std::span(iArr2, 4), 3); + + std::string s; + testRuntimeSpan(std::span (&s, 1), 0); + testRuntimeSpan(std::span(&s, 1), 0); +} diff --git a/test/std/containers/views/span.iterators/begin.pass.cpp b/test/std/containers/views/span.iterators/begin.pass.cpp new file mode 100644 index 000000000..c8b9900bc --- /dev/null +++ b/test/std/containers/views/span.iterators/begin.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr iterator begin() const noexcept; +// constexpr const_iterator cbegin() const noexcept; + +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool testConstexprSpan(Span s) +{ + bool ret = true; + typename Span::iterator b = s. begin(); + typename Span::const_iterator cb = s.cbegin(); + + if (s.empty()) + { + ret = ret && ( b == s.end()); + ret = ret && (cb == s.cend()); + } + else + { + ret = ret && ( *b == s[0]); + ret = ret && ( &*b == &s[0]); + ret = ret && ( *cb == s[0]); + ret = ret && (&*cb == &s[0]); + } + ret = ret && (b == cb); + return ret; +} + + +template +void testRuntimeSpan(Span s) +{ + typename Span::iterator b = s. begin(); + typename Span::const_iterator cb = s.cbegin(); + + if (s.empty()) + { + assert( b == s.end()); + assert(cb == s.cend()); + } + else + { + assert( *b == s[0]); + assert( &*b == &s[0]); + assert( *cb == s[0]); + assert(&*cb == &s[0]); + } + assert(b == cb); +} + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + +int main() +{ + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 5)), ""); + + + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span(iArr2, 1)); + testRuntimeSpan(std::span(iArr2, 2)); + testRuntimeSpan(std::span(iArr2, 3)); + testRuntimeSpan(std::span(iArr2, 4)); + testRuntimeSpan(std::span(iArr2, 5)); + + std::string s; + testRuntimeSpan(std::span(&s, (std::ptrdiff_t) 0)); + testRuntimeSpan(std::span(&s, 1)); +} diff --git a/test/std/containers/views/span.iterators/end.pass.cpp b/test/std/containers/views/span.iterators/end.pass.cpp new file mode 100644 index 000000000..2b64b0f4b --- /dev/null +++ b/test/std/containers/views/span.iterators/end.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr iterator end() const noexcept; +// constexpr const_iterator cend() const noexcept; + +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool testConstexprSpan(Span s) +{ + bool ret = true; + typename Span::iterator e = s. end(); + typename Span::const_iterator ce = s.cend(); + if (s.empty()) + { + ret = ret && ( e == s.begin()); + ret = ret && (ce == s.cbegin()); + } + else + { + ret = ret && ( e != s.begin()); + ret = ret && (ce != s.cbegin()); + } + + ret = ret && (( e - s.begin()) == s.size()); + ret = ret && ((ce - s.cbegin()) == s.size()); + + ret = ret && (e == ce); + return ret; +} + +template +void testRuntimeSpan(Span s) +{ + typename Span::iterator e = s. end(); + typename Span::const_iterator ce = s.cend(); + if (s.empty()) + { + assert( e == s.begin()); + assert(ce == s.cbegin()); + } + else + { + assert( e != s.begin()); + assert(ce != s.cbegin()); + } + + assert(( e - s.begin()) == s.size()); + assert((ce - s.cbegin()) == s.size()); + + assert(e == ce); +} + + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + +int main() +{ + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 5)), ""); + + + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span(iArr2, 1)); + testRuntimeSpan(std::span(iArr2, 2)); + testRuntimeSpan(std::span(iArr2, 3)); + testRuntimeSpan(std::span(iArr2, 4)); + testRuntimeSpan(std::span(iArr2, 5)); + + std::string s; + testRuntimeSpan(std::span(&s, (std::ptrdiff_t) 0)); + testRuntimeSpan(std::span(&s, 1)); +} diff --git a/test/std/containers/views/span.iterators/rbegin.pass.cpp b/test/std/containers/views/span.iterators/rbegin.pass.cpp new file mode 100644 index 000000000..c0776c00a --- /dev/null +++ b/test/std/containers/views/span.iterators/rbegin.pass.cpp @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr reverse_iterator rbegin() const noexcept; +// constexpr const_reverse_iterator crbegin() const noexcept; + +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool testConstexprSpan(Span s) +{ + bool ret = true; + typename Span::reverse_iterator b = s. rbegin(); + typename Span::const_reverse_iterator cb = s.crbegin(); + if (s.empty()) + { + ret = ret && ( b == s.rend()); + ret = ret && (cb == s.crend()); + } + else + { + const typename Span::index_type last = s.size() - 1; + ret = ret && ( *b == s[last]); + ret = ret && ( &*b == &s[last]); + ret = ret && ( *cb == s[last]); + ret = ret && (&*cb == &s[last]); + } + ret = ret && (b == cb); + return ret; +} + + +template +void testRuntimeSpan(Span s) +{ + typename Span::reverse_iterator b = s. rbegin(); + typename Span::const_reverse_iterator cb = s.crbegin(); + if (s.empty()) + { + assert( b == s.rend()); + assert(cb == s.crend()); + } + else + { + const typename Span::index_type last = s.size() - 1; + assert( *b == s[last]); + assert( &*b == &s[last]); + assert( *cb == s[last]); + assert(&*cb == &s[last]); + } + assert(b == cb); +} + + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + +int main() +{ + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 5)), ""); + + + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span(iArr2, 1)); + testRuntimeSpan(std::span(iArr2, 2)); + testRuntimeSpan(std::span(iArr2, 3)); + testRuntimeSpan(std::span(iArr2, 4)); + testRuntimeSpan(std::span(iArr2, 5)); + + std::string s; + testRuntimeSpan(std::span(&s, static_cast(0))); + testRuntimeSpan(std::span(&s, 1)); +} diff --git a/test/std/containers/views/span.iterators/rend.pass.cpp b/test/std/containers/views/span.iterators/rend.pass.cpp new file mode 100644 index 000000000..abcead445 --- /dev/null +++ b/test/std/containers/views/span.iterators/rend.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr reverse_iterator rend() const noexcept; +// constexpr const_reverse_iterator crend() const noexcept; + +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool testConstexprSpan(Span s) +{ + bool ret = true; + typename Span::reverse_iterator e = s. rend(); + typename Span::const_reverse_iterator ce = s.crend(); + if (s.empty()) + { + ret = ret && ( e == s.rbegin()); + ret = ret && (ce == s.crbegin()); + } + else + { + ret = ret && ( e != s.rbegin()); + ret = ret && (ce != s.crbegin()); + } + + ret = ret && (( e - s.rbegin()) == s.size()); + ret = ret && ((ce - s.crbegin()) == s.size()); + + ret = ret && (e == ce); + return ret; +} + +template +void testRuntimeSpan(Span s) +{ + typename Span::reverse_iterator e = s. rend(); + typename Span::const_reverse_iterator ce = s.crend(); + if (s.empty()) + { + assert( e == s.rbegin()); + assert(ce == s.crbegin()); + } + else + { + assert( e != s.rbegin()); + assert(ce != s.crbegin()); + } + + assert(( e - s.rbegin()) == s.size()); + assert((ce - s.crbegin()) == s.size()); + + assert(e == ce); +} + + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + +int main() +{ + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + static_assert(testConstexprSpan(std::span()), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 5)), ""); + + + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span(iArr2, 1)); + testRuntimeSpan(std::span(iArr2, 2)); + testRuntimeSpan(std::span(iArr2, 3)); + testRuntimeSpan(std::span(iArr2, 4)); + testRuntimeSpan(std::span(iArr2, 5)); + + std::string s; + testRuntimeSpan(std::span(&s, (std::ptrdiff_t) 0)); + testRuntimeSpan(std::span(&s, 1)); +} diff --git a/test/std/containers/views/span.objectrep/as_bytes.pass.cpp b/test/std/containers/views/span.objectrep/as_bytes.pass.cpp new file mode 100644 index 000000000..b081b95c3 --- /dev/null +++ b/test/std/containers/views/span.objectrep/as_bytes.pass.cpp @@ -0,0 +1,78 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// span(sizeof(ElementType)) * Extent> +// as_bytes(span s) noexcept; + + +#include +#include +#include + +#include "test_macros.h" + +template +void testRuntimeSpan(Span sp) +{ + ASSERT_NOEXCEPT(std::as_bytes(sp)); + + auto spBytes = std::as_bytes(sp); + using SB = decltype(spBytes); + ASSERT_SAME_TYPE(const std::byte, typename SB::element_type); + + if (sp.extent == std::dynamic_extent) + assert(spBytes.extent == std::dynamic_extent); + else + assert(spBytes.extent == static_cast(sizeof(typename Span::element_type)) * sp.extent); + + assert((void *) spBytes.data() == (void *) sp.data()); + assert(spBytes.size() == sp.size_bytes()); +} + +struct A{}; +int iArr2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + +int main () +{ + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span(iArr2, 1)); + testRuntimeSpan(std::span(iArr2, 2)); + testRuntimeSpan(std::span(iArr2, 3)); + testRuntimeSpan(std::span(iArr2, 4)); + testRuntimeSpan(std::span(iArr2, 5)); + + testRuntimeSpan(std::span(iArr2 + 5, 1)); + testRuntimeSpan(std::span(iArr2 + 4, 2)); + testRuntimeSpan(std::span(iArr2 + 3, 3)); + testRuntimeSpan(std::span(iArr2 + 2, 4)); + testRuntimeSpan(std::span(iArr2 + 1, 5)); + + std::string s; + testRuntimeSpan(std::span(&s, (std::ptrdiff_t) 0)); + testRuntimeSpan(std::span(&s, 1)); +} diff --git a/test/std/containers/views/span.objectrep/as_writeable_bytes.fail.cpp b/test/std/containers/views/span.objectrep/as_writeable_bytes.fail.cpp new file mode 100644 index 000000000..28a4c45d2 --- /dev/null +++ b/test/std/containers/views/span.objectrep/as_writeable_bytes.fail.cpp @@ -0,0 +1,48 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// span(sizeof(ElementType)) * Extent> +// as_writeable_bytes(span s) noexcept; + + +#include +#include +#include + +#include "test_macros.h" + +const int iArr2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + +struct A {}; + +int main () +{ + std::as_writeable_bytes(std::span()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + + std::as_writeable_bytes(std::span()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + + std::as_writeable_bytes(std::span (iArr2, 1)); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span(iArr2 + 5, 1)); // expected-error {{no matching function for call to 'as_writeable_bytes'}} +} diff --git a/test/std/containers/views/span.objectrep/as_writeable_bytes.pass.cpp b/test/std/containers/views/span.objectrep/as_writeable_bytes.pass.cpp new file mode 100644 index 000000000..24e3fb273 --- /dev/null +++ b/test/std/containers/views/span.objectrep/as_writeable_bytes.pass.cpp @@ -0,0 +1,78 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// span(sizeof(ElementType)) * Extent> +// as_writeable_bytes(span s) noexcept; + + +#include +#include +#include + +#include "test_macros.h" + +template +void testRuntimeSpan(Span sp) +{ + ASSERT_NOEXCEPT(std::as_writeable_bytes(sp)); + + auto spBytes = std::as_writeable_bytes(sp); + using SB = decltype(spBytes); + ASSERT_SAME_TYPE(std::byte, typename SB::element_type); + + if (sp.extent == std::dynamic_extent) + assert(spBytes.extent == std::dynamic_extent); + else + assert(spBytes.extent == static_cast(sizeof(typename Span::element_type)) * sp.extent); + + assert(static_cast(spBytes.data()) == static_cast(sp.data())); + assert(spBytes.size() == sp.size_bytes()); +} + +struct A{}; +int iArr2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + +int main () +{ + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span ()); + testRuntimeSpan(std::span()); + + testRuntimeSpan(std::span(iArr2, 1)); + testRuntimeSpan(std::span(iArr2, 2)); + testRuntimeSpan(std::span(iArr2, 3)); + testRuntimeSpan(std::span(iArr2, 4)); + testRuntimeSpan(std::span(iArr2, 5)); + + testRuntimeSpan(std::span(iArr2 + 5, 1)); + testRuntimeSpan(std::span(iArr2 + 4, 2)); + testRuntimeSpan(std::span(iArr2 + 3, 3)); + testRuntimeSpan(std::span(iArr2 + 2, 4)); + testRuntimeSpan(std::span(iArr2 + 1, 5)); + + std::string s; + testRuntimeSpan(std::span(&s, (std::ptrdiff_t) 0)); + testRuntimeSpan(std::span(&s, 1)); +} diff --git a/test/std/containers/views/span.obs/empty.pass.cpp b/test/std/containers/views/span.obs/empty.pass.cpp new file mode 100644 index 000000000..a48c0d024 --- /dev/null +++ b/test/std/containers/views/span.obs/empty.pass.cpp @@ -0,0 +1,73 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr bool empty() const noexcept; +// + + +#include +#include +#include + +#include "test_macros.h" + +struct A{}; +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +int main () +{ + static_assert( noexcept(std::span ().empty()), ""); + static_assert( noexcept(std::span().empty()), ""); + + + static_assert( std::span().empty(), ""); + static_assert( std::span().empty(), ""); + static_assert( std::span().empty(), ""); + static_assert( std::span().empty(), ""); + static_assert( std::span().empty(), ""); + + static_assert( std::span().empty(), ""); + static_assert( std::span().empty(), ""); + static_assert( std::span().empty(), ""); + static_assert( std::span().empty(), ""); + static_assert( std::span().empty(), ""); + + static_assert(!std::span(iArr1, 1).empty(), ""); + static_assert(!std::span(iArr1, 2).empty(), ""); + static_assert(!std::span(iArr1, 3).empty(), ""); + static_assert(!std::span(iArr1, 4).empty(), ""); + static_assert(!std::span(iArr1, 5).empty(), ""); + + assert( (std::span().empty() )); + assert( (std::span().empty() )); + assert( (std::span().empty() )); + assert( (std::span().empty() )); + assert( (std::span().empty() )); + + assert( (std::span().empty() )); + assert( (std::span().empty() )); + assert( (std::span().empty() )); + assert( (std::span().empty() )); + assert( (std::span().empty())); + + assert(!(std::span(iArr2, 1).empty())); + assert(!(std::span(iArr2, 2).empty())); + assert(!(std::span(iArr2, 3).empty())); + assert(!(std::span(iArr2, 4).empty())); + assert(!(std::span(iArr2, 5).empty())); + + std::string s; + assert( ((std::span(&s, (std::ptrdiff_t) 0)).empty())); + assert(!((std::span(&s, 1).empty()))); +} diff --git a/test/std/containers/views/span.obs/size.pass.cpp b/test/std/containers/views/span.obs/size.pass.cpp new file mode 100644 index 000000000..c33fd3f6c --- /dev/null +++ b/test/std/containers/views/span.obs/size.pass.cpp @@ -0,0 +1,91 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr index_type size() const noexcept; +// + + +#include +#include +#include + +#include "test_macros.h" + + +template +constexpr bool testConstexprSpan(Span sp, ptrdiff_t sz) +{ + ASSERT_NOEXCEPT(sp.size()); + return sp.size() == sz; +} + + +template +void testRuntimeSpan(Span sp, ptrdiff_t sz) +{ + ASSERT_NOEXCEPT(sp.size()); + assert(sp.size() == sz); +} + +struct A{}; +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +int main () +{ + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 1), 1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2), 2), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3), 3), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4), 4), ""); + static_assert(testConstexprSpan(std::span(iArr1, 5), 5), ""); + + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span(), 0); + + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span(), 0); + + testRuntimeSpan(std::span(iArr2, 1), 1); + testRuntimeSpan(std::span(iArr2, 2), 2); + testRuntimeSpan(std::span(iArr2, 3), 3); + testRuntimeSpan(std::span(iArr2, 4), 4); + testRuntimeSpan(std::span(iArr2, 5), 5); + + testRuntimeSpan(std::span(iArr2 + 5, 1), 1); + testRuntimeSpan(std::span(iArr2 + 4, 2), 2); + testRuntimeSpan(std::span(iArr2 + 3, 3), 3); + testRuntimeSpan(std::span(iArr2 + 2, 4), 4); + testRuntimeSpan(std::span(iArr2 + 1, 5), 5); + + std::string s; + testRuntimeSpan(std::span(&s, (std::ptrdiff_t) 0), 0); + testRuntimeSpan(std::span(&s, 1), 1); +} diff --git a/test/std/containers/views/span.obs/size_bytes.pass.cpp b/test/std/containers/views/span.obs/size_bytes.pass.cpp new file mode 100644 index 000000000..1ee75d9fc --- /dev/null +++ b/test/std/containers/views/span.obs/size_bytes.pass.cpp @@ -0,0 +1,92 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// constexpr index_type size_bytes() const noexcept; +// +// Effects: Equivalent to: return size() * sizeof(element_type); + + +#include +#include +#include + +#include "test_macros.h" + + +template +constexpr bool testConstexprSpan(Span sp, ptrdiff_t sz) +{ + ASSERT_NOEXCEPT(sp.size_bytes()); + return (size_t) sp.size_bytes() == sz * sizeof(typename Span::element_type); +} + + +template +void testRuntimeSpan(Span sp, ptrdiff_t sz) +{ + ASSERT_NOEXCEPT(sp.size_bytes()); + assert((size_t) sp.size_bytes() == sz * sizeof(typename Span::element_type)); +} + +struct A{}; +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +int main () +{ + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + static_assert(testConstexprSpan(std::span(), 0), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 1), 1), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2), 2), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3), 3), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4), 4), ""); + static_assert(testConstexprSpan(std::span(iArr1, 5), 5), ""); + + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span(), 0); + + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span (), 0); + testRuntimeSpan(std::span(), 0); + + testRuntimeSpan(std::span(iArr2, 1), 1); + testRuntimeSpan(std::span(iArr2, 2), 2); + testRuntimeSpan(std::span(iArr2, 3), 3); + testRuntimeSpan(std::span(iArr2, 4), 4); + testRuntimeSpan(std::span(iArr2, 5), 5); + + testRuntimeSpan(std::span(iArr2 + 5, 1), 1); + testRuntimeSpan(std::span(iArr2 + 4, 2), 2); + testRuntimeSpan(std::span(iArr2 + 3, 3), 3); + testRuntimeSpan(std::span(iArr2 + 2, 4), 4); + testRuntimeSpan(std::span(iArr2 + 1, 5), 5); + + std::string s; + testRuntimeSpan(std::span(&s, (std::ptrdiff_t) 0), 0); + testRuntimeSpan(std::span(&s, 1), 1); +} diff --git a/test/std/containers/views/span.sub/first.pass.cpp b/test/std/containers/views/span.sub/first.pass.cpp new file mode 100644 index 000000000..3bfdab9f8 --- /dev/null +++ b/test/std/containers/views/span.sub/first.pass.cpp @@ -0,0 +1,136 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr span first() const; +// +// constexpr span first(index_type count) const; +// +// Requires: 0 <= Count && Count <= size(). + + +#include +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool testConstexprSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template first()))); + LIBCPP_ASSERT((noexcept(sp.first(Count)))); + auto s1 = sp.template first(); + auto s2 = sp.first(Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == Count, ""); + static_assert(S2::extent == std::dynamic_extent, ""); + return + s1.data() == s2.data() + && s1.size() == s2.size() + && std::equal(s1.begin(), s1.end(), sp.begin()); +} + + +template +void testRuntimeSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template first()))); + LIBCPP_ASSERT((noexcept(sp.first(Count)))); + auto s1 = sp.template first(); + auto s2 = sp.first(Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == Count, ""); + static_assert(S2::extent == std::dynamic_extent, ""); + assert(s1.data() == s2.data()); + assert(s1.size() == s2.size()); + assert(std::equal(s1.begin(), s1.end(), sp.begin())); +} + + +constexpr int carr1[] = {1,2,3,4}; + int arr[] = {5,6,7}; +std::string sarr [] = { "ABC", "DEF", "GHI", "JKL", "MNO"}; + +int main () +{ + { + using Sp = std::span; + static_assert(testConstexprSpan(Sp{}), ""); + + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + } + + { + using Sp = std::span; + + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + } + + { + using Sp = std::span; + testRuntimeSpan(Sp{}); + + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + } + + { + using Sp = std::span; + + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + } + + { + using Sp = std::span; + testConstexprSpan(Sp{}); + + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + } + + { + using Sp = std::span; + + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + } +} diff --git a/test/std/containers/views/span.sub/last.pass.cpp b/test/std/containers/views/span.sub/last.pass.cpp new file mode 100644 index 000000000..4e378fe54 --- /dev/null +++ b/test/std/containers/views/span.sub/last.pass.cpp @@ -0,0 +1,136 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr span last() const; +// +// constexpr span last(index_type count) const; +// +// Requires: 0 <= Count && Count <= size(). + + +#include +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool testConstexprSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template last()))); + LIBCPP_ASSERT((noexcept(sp.last(Count)))); + auto s1 = sp.template last(); + auto s2 = sp.last(Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == Count, ""); + static_assert(S2::extent == std::dynamic_extent, ""); + return + s1.data() == s2.data() + && s1.size() == s2.size() + && std::equal(s1.begin(), s1.end(), sp.end() - Count); +} + + +template +void testRuntimeSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template last()))); + LIBCPP_ASSERT((noexcept(sp.last(Count)))); + auto s1 = sp.template last(); + auto s2 = sp.last(Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == Count, ""); + static_assert(S2::extent == std::dynamic_extent, ""); + assert(s1.data() == s2.data()); + assert(s1.size() == s2.size()); + assert(std::equal(s1.begin(), s1.end(), sp.end() - Count)); +} + + +constexpr int carr1[] = {1,2,3,4}; + int arr[] = {5,6,7}; +std::string sarr [] = { "ABC", "DEF", "GHI", "JKL", "MNO"}; + +int main () +{ + { + using Sp = std::span; + static_assert(testConstexprSpan(Sp{}), ""); + + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + } + + { + using Sp = std::span; + + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + } + + { + using Sp = std::span; + testRuntimeSpan(Sp{}); + + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + } + + { + using Sp = std::span; + + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + testRuntimeSpan(Sp{arr}); + } + + { + using Sp = std::span; + testConstexprSpan(Sp{}); + + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + } + + { + using Sp = std::span; + + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + testRuntimeSpan(Sp{sarr}); + } +} diff --git a/test/std/containers/views/span.sub/subspan.pass.cpp b/test/std/containers/views/span.sub/subspan.pass.cpp new file mode 100644 index 000000000..79cdc7bca --- /dev/null +++ b/test/std/containers/views/span.sub/subspan.pass.cpp @@ -0,0 +1,210 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// constexpr span subspan() const; +// +// constexpr span subspan( +// index_type offset, index_type count = dynamic_extent) const; +// +// Requires: (0 <= Offset && Offset <= size()) +// && (Count == dynamic_extent || Count >= 0 && Offset + Count <= size()) + +#include +#include +#include +#include + +#include "test_macros.h" + +template +constexpr bool testConstexprSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template subspan()))); + LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count)))); + auto s1 = sp.template subspan(); + auto s2 = sp.subspan(Offset, Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Count), ""); + static_assert(S2::extent == std::dynamic_extent, ""); + return + s1.data() == s2.data() + && s1.size() == s2.size() + && std::equal(s1.begin(), s1.end(), sp.begin() + Offset); +} + +template +constexpr bool testConstexprSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template subspan()))); + LIBCPP_ASSERT((noexcept(sp.subspan(Offset)))); + auto s1 = sp.template subspan(); + auto s2 = sp.subspan(Offset); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), ""); + static_assert(S2::extent == std::dynamic_extent, ""); + return + s1.data() == s2.data() + && s1.size() == s2.size() + && std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end()); +} + + +template +void testRuntimeSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template subspan()))); + LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count)))); + auto s1 = sp.template subspan(); + auto s2 = sp.subspan(Offset, Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Count), ""); + static_assert(S2::extent == std::dynamic_extent, ""); + assert(s1.data() == s2.data()); + assert(s1.size() == s2.size()); + assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset)); +} + + +template +void testRuntimeSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template subspan()))); + LIBCPP_ASSERT((noexcept(sp.subspan(Offset)))); + auto s1 = sp.template subspan(); + auto s2 = sp.subspan(Offset); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), ""); + static_assert(S2::extent == std::dynamic_extent, ""); + assert(s1.data() == s2.data()); + assert(s1.size() == s2.size()); + assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end())); +} + + +constexpr int carr1[] = {1,2,3,4}; + int arr1[] = {5,6,7}; + +int main () +{ + { + using Sp = std::span; + static_assert(testConstexprSpan(Sp{}), ""); + + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + } + + { + using Sp = std::span; + + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + } + + { + using Sp = std::span; + static_assert(testConstexprSpan(Sp{}), ""); + + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + } + + { + using Sp = std::span; + + static_assert(testConstexprSpan(Sp{carr1}), ""); + + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + static_assert(testConstexprSpan(Sp{carr1}), ""); + } + + { + using Sp = std::span; + testRuntimeSpan(Sp{}); + + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + } + + { + using Sp = std::span; + + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + } + + { + using Sp = std::span; + testRuntimeSpan(Sp{}); + + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + } + + { + using Sp = std::span; + + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + testRuntimeSpan(Sp{arr1}); + } +} diff --git a/test/std/containers/views/types.pass.cpp b/test/std/containers/views/types.pass.cpp new file mode 100644 index 000000000..082abeb77 --- /dev/null +++ b/test/std/containers/views/types.pass.cpp @@ -0,0 +1,107 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// template +// class span { +// public: +// // constants and types +// using element_type = ElementType; +// using value_type = remove_cv_t; +// using index_type = ptrdiff_t; +// using difference_type = ptrdiff_t; +// using pointer = element_type *; +// using reference = element_type &; +// using iterator = implementation-defined; +// using const_iterator = implementation-defined; +// using reverse_iterator = std::reverse_iterator; +// using const_reverse_iterator = std::reverse_iterator; +// +// static constexpr index_type extent = Extent; +// + +#include +#include +#include +#include + +#include "test_macros.h" + +template +void testIterator() +{ + typedef std::iterator_traits ItT; + + ASSERT_SAME_TYPE(typename ItT::iterator_category, std::random_access_iterator_tag); + ASSERT_SAME_TYPE(typename ItT::value_type, typename S::value_type); + ASSERT_SAME_TYPE(typename ItT::reference, typename S::reference); + ASSERT_SAME_TYPE(typename ItT::pointer, typename S::pointer); + ASSERT_SAME_TYPE(typename ItT::difference_type, typename S::difference_type); +} + +template +void testConstIterator() +{ + typedef std::iterator_traits ItT; + + ASSERT_SAME_TYPE(typename ItT::iterator_category, std::random_access_iterator_tag); + ASSERT_SAME_TYPE(typename ItT::value_type, typename S::value_type); +// I'd like to say 'const typename S::pointer' here, but that gives me +// a const pointer to a non-const value, which is not what I want. + ASSERT_SAME_TYPE(typename ItT::reference, typename S::element_type const &); + ASSERT_SAME_TYPE(typename ItT::pointer, typename S::element_type const *); + ASSERT_SAME_TYPE(typename ItT::difference_type, typename S::difference_type); +} + +template +void testSpan() +{ + ASSERT_SAME_TYPE(typename S::element_type, ElementType); + ASSERT_SAME_TYPE(typename S::value_type, std::remove_cv_t); + ASSERT_SAME_TYPE(typename S::index_type, std::ptrdiff_t); + ASSERT_SAME_TYPE(typename S::difference_type, std::ptrdiff_t); + ASSERT_SAME_TYPE(typename S::pointer, ElementType *); + ASSERT_SAME_TYPE(typename S::reference, ElementType &); + + static_assert(S::extent == Size); // check that it exists + + testIterator(); + testIterator(); + testConstIterator(); + testConstIterator(); +} + + +template +void test() +{ + testSpan, T, -1>(); + testSpan, const T, -1>(); + testSpan, volatile T, -1>(); + testSpan, const volatile T, -1>(); + + testSpan, T, 5>(); + testSpan, const T, 5>(); + testSpan, volatile T, 5>(); + testSpan, const volatile T, 5>(); +} + +struct A{}; + +int main () +{ + test(); + test(); + test(); + test(); + test(); +} -- GitLab From dfd0874465ed20df924123b3af1e8d5b629e8001 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 24 Jul 2018 03:41:36 +0000 Subject: [PATCH 063/495] Disable 'suggest braces' warnings for std::array in tests git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337808 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/std/containers/views/span.cons/deduct.pass.cpp | 4 ++++ test/std/containers/views/span.cons/stdarray.pass.cpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/test/std/containers/views/span.cons/deduct.pass.cpp b/test/std/containers/views/span.cons/deduct.pass.cpp index 3410bb31c..e72c09149 100644 --- a/test/std/containers/views/span.cons/deduct.pass.cpp +++ b/test/std/containers/views/span.cons/deduct.pass.cpp @@ -37,6 +37,10 @@ #include "test_macros.h" +// std::array is explicitly allowed to be initialized with A a = { init-list };. +// Disable the missing braces warning for this reason. +#include "disable_missing_braces_warning.h" + int main () { { diff --git a/test/std/containers/views/span.cons/stdarray.pass.cpp b/test/std/containers/views/span.cons/stdarray.pass.cpp index 204935db0..1832ac2ba 100644 --- a/test/std/containers/views/span.cons/stdarray.pass.cpp +++ b/test/std/containers/views/span.cons/stdarray.pass.cpp @@ -27,6 +27,9 @@ #include #include "test_macros.h" +// std::array is explicitly allowed to be initialized with A a = { init-list };. +// Disable the missing braces warning for this reason. +#include "disable_missing_braces_warning.h" void checkCV() -- GitLab From 39bc5e758b269c9e09aee2b1b028e4bfb59ddcb2 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 24 Jul 2018 03:56:38 +0000 Subject: [PATCH 064/495] fix nesting of namespace and standard-version check. Also include <__config> git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337809 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/span | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/span b/include/span index b1a13dd02..db8f836f9 100644 --- a/include/span +++ b/include/span @@ -140,6 +140,7 @@ template */ +#include <__config> #include // for ptrdiff_t #include // for iterators #include // for array @@ -600,7 +601,8 @@ template template span(const _Container&) -> span; +#endif // _LIBCPP_STD_VER > 17 + _LIBCPP_END_NAMESPACE_STD -#endif // _LIBCPP_STD_VER > 17 #endif // _LIBCPP_SPAN -- GitLab From 44ef94a8c98717d13749798d7486b3676c40ea99 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 24 Jul 2018 07:06:17 +0000 Subject: [PATCH 065/495] Reland "[CMake] Support statically linking dependencies only to shared or static library" This is a reland of commit r337668. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337814 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 8 ++++++++ cmake/Modules/HandleLibCXXABI.cmake | 6 +++--- lib/CMakeLists.txt | 6 +++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6521ebbe4..df59b5610 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,14 @@ endif() # cannot be used with LIBCXX_ENABLE_ABI_LINKER_SCRIPT. option(LIBCXX_ENABLE_STATIC_ABI_LIBRARY "Statically link the ABI library" OFF) +cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY + "Statically link the ABI library to static library" ON + "LIBCXX_ENABLE_STATIC_ABI_LIBRARY;LIBCXX_ENABLE_STATIC" OFF) + +cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY + "Statically link the ABI library to shared library" ON + "LIBCXX_ENABLE_STATIC_ABI_LIBRARY;LIBCXX_ENABLE_STATIC" OFF) + # Generate and install a linker script inplace of libc++.so. The linker script # will link libc++ to the correct ABI library. This option is on by default # on UNIX platforms other than Apple unless 'LIBCXX_ENABLE_STATIC_ABI_LIBRARY' diff --git a/cmake/Modules/HandleLibCXXABI.cmake b/cmake/Modules/HandleLibCXXABI.cmake index 0eb70a739..d837c3c37 100644 --- a/cmake/Modules/HandleLibCXXABI.cmake +++ b/cmake/Modules/HandleLibCXXABI.cmake @@ -96,10 +96,10 @@ if ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libstdc++" OR elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxabi") if (LIBCXX_CXX_ABI_INTREE) # Link against just-built "cxxabi" target. - if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) - set(CXXABI_LIBNAME cxxabi_static) + if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY) + set(CXXABI_LIBNAME cxxabi_static) else() - set(CXXABI_LIBNAME cxxabi_shared) + set(CXXABI_LIBNAME cxxabi_shared) endif() set(LIBCXX_LIBCPPABI_VERSION "2" PARENT_SCOPE) else() diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index d32f8fb8e..5ac691a75 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -44,7 +44,7 @@ if (APPLE AND (LIBCXX_CXX_ABI_LIBNAME STREQUAL "libcxxabi" OR set(LIBCXX_OSX_REEXPORT_SYSTEM_ABI_LIBRARY ON) endif() -if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) +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") @@ -259,14 +259,14 @@ if (LIBCXX_ENABLE_STATIC) list(APPEND LIBCXX_TARGETS "cxx_static") # Attempt to merge the libc++.a archive and the ABI library archive into one. - if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY) + if (LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY) set(MERGE_ARCHIVES_SEARCH_PATHS "") if (LIBCXX_CXX_ABI_LIBRARY_PATH) set(MERGE_ARCHIVES_SEARCH_PATHS "-L${LIBCXX_CXX_ABI_LIBRARY_PATH}") endif() if ((TARGET ${LIBCXX_CXX_ABI_LIBRARY}) OR (${LIBCXX_CXX_ABI_LIBRARY} MATCHES "cxxabi(_static|_shared)?" AND HAVE_LIBCXXABI)) - set(MERGE_ARCHIVES_ABI_TARGET "$") + set(MERGE_ARCHIVES_ABI_TARGET "$") else() set(MERGE_ARCHIVES_ABI_TARGET "${CMAKE_STATIC_LIBRARY_PREFIX}${LIBCXX_CXX_ABI_LIBRARY}${CMAKE_STATIC_LIBRARY_SUFFIX}") -- GitLab From ad7e93552d0daf2e3be20a207b047e58c0db0eeb Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Tue, 24 Jul 2018 09:15:03 +0000 Subject: [PATCH 066/495] Fix use of incorrect _LIBCXX macro (should be _LIBCPP). git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337817 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/future | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/future b/include/future index 528091b04..0f6d42678 100644 --- a/include/future +++ b/include/future @@ -409,7 +409,7 @@ _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(launch) #ifndef _LIBCPP_HAS_NO_STRONG_ENUMS -#ifdef _LIBCXX_UNDERLYING_TYPE +#ifdef _LIBCPP_UNDERLYING_TYPE typedef underlying_type::type __launch_underlying_type; #else typedef int __launch_underlying_type; -- GitLab From 2be41bb90bc8613e4a2ae4fa5efe10b87c139e50 Mon Sep 17 00:00:00 2001 From: Alexander Richardson Date: Tue, 24 Jul 2018 12:40:56 +0000 Subject: [PATCH 067/495] Stop wrapping __has_include in another macro Summary: This is not guaranteed to work since the characters after '__has_include(' have special lexing rules that can't possibly be applied when __has_include is generated by a macro. It also breaks the crash reproducers generated by -frewrite-includes (see https://llvm.org/pr37990). Reviewers: EricWF, rsmith, mclow.lists Reviewed By: mclow.lists Differential Revision: https://reviews.llvm.org/D49067 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337824 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__config | 8 +++----- test/support/test_macros.h | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/include/__config b/include/__config index 49b8fd79f..f659ba943 100644 --- a/include/__config +++ b/include/__config @@ -149,10 +149,8 @@ #define __has_keyword(__x) !(__is_identifier(__x)) -#ifdef __has_include -# define __libcpp_has_include(__x) __has_include(__x) -#else -# define __libcpp_has_include(__x) 0 +#ifndef __has_include +#define __has_include(...) 0 #endif #if defined(__clang__) @@ -1066,7 +1064,7 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container( defined(__APPLE__) || \ defined(__CloudABI__) || \ defined(__sun__) || \ - (defined(__MINGW32__) && __libcpp_has_include()) + (defined(__MINGW32__) && __has_include()) # define _LIBCPP_HAS_THREAD_API_PTHREAD # elif defined(_LIBCPP_WIN32API) # define _LIBCPP_HAS_THREAD_API_WIN32 diff --git a/test/support/test_macros.h b/test/support/test_macros.h index 5d38bcfc6..dbbfd5309 100644 --- a/test/support/test_macros.h +++ b/test/support/test_macros.h @@ -27,10 +27,8 @@ #define TEST_HAS_FEATURE(X) 0 #endif -#ifdef __has_include -#define TEST_HAS_INCLUDE(X) __has_include(X) -#else -#define TEST_HAS_INCLUDE(X) 0 +#ifndef __has_include +#define __has_include(...) 0 #endif #ifdef __has_extension @@ -90,7 +88,7 @@ #endif // Attempt to deduce GCC version -#if defined(_LIBCPP_VERSION) && TEST_HAS_INCLUDE() +#if defined(_LIBCPP_VERSION) && __has_include() #include #define TEST_HAS_GLIBC #define TEST_GLIBC_PREREQ(major, minor) __GLIBC_PREREQ(major, minor) -- GitLab From 83f3cdc6a4e1033fb0f16f418c4b698b3030e29a Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 24 Jul 2018 15:49:29 +0000 Subject: [PATCH 068/495] [CMake] Fix the setting of LIBCXX_HEADER_DIR in standalone build This is an alternative approach to r337727 which broke the build because libc++ headers were copied into the location outside of directories used by Clang. This change sets LIBCXX_HEADER_DIR to different values depending on whether libc++ is being built as part of LLVM w/ per-target multiarch runtime, LLVM or standalone. Differential Revision: https://reviews.llvm.org/D49711 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337833 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 3 ++- cmake/Modules/HandleLibCXXABI.cmake | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df59b5610..549be42e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -386,7 +386,6 @@ endif () set(LIBCXX_COMPILER ${CMAKE_CXX_COMPILER}) set(LIBCXX_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(LIBCXX_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) -set(LIBCXX_HEADER_DIR ${LLVM_BINARY_DIR}) set(LIBCXX_BINARY_INCLUDE_DIR "${LIBCXX_BINARY_DIR}/include/c++build") string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION @@ -399,8 +398,10 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE) set(LIBCXX_HEADER_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}) elseif(LLVM_LIBRARY_OUTPUT_INTDIR) set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) + set(LIBCXX_HEADER_DIR ${LLVM_BINARY_DIR}) else() set(LIBCXX_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXX_LIBDIR_SUFFIX}) + set(LIBCXX_HEADER_DIR ${CMAKE_BINARY_DIR}) endif() file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}") diff --git a/cmake/Modules/HandleLibCXXABI.cmake b/cmake/Modules/HandleLibCXXABI.cmake index d837c3c37..54b1e1286 100644 --- a/cmake/Modules/HandleLibCXXABI.cmake +++ b/cmake/Modules/HandleLibCXXABI.cmake @@ -48,12 +48,14 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs) COMMENT "Copying C++ ABI header ${fpath}...") list(APPEND abilib_headers "${dst}") - set(dst "${LIBCXX_HEADER_DIR}/include/c++/v1/${dstdir}/${fpath}") - add_custom_command(OUTPUT ${dst} - DEPENDS ${src} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} - COMMENT "Copying C++ ABI header ${fpath}...") - list(APPEND abilib_headers "${dst}") + if (NOT LIBCXX_USING_INSTALLED_LLVM) + set(dst "${LIBCXX_HEADER_DIR}/include/c++/v1/${dstdir}/${fpath}") + add_custom_command(OUTPUT ${dst} + DEPENDS ${src} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} + COMMENT "Copying C++ ABI header ${fpath}...") + list(APPEND abilib_headers "${dst}") + endif() if (LIBCXX_INSTALL_HEADERS) install(FILES "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}" -- GitLab From 89d973a050d8b0ec10f7c03dd7d6ab1a45f69c6f Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Tue, 24 Jul 2018 23:27:51 +0000 Subject: [PATCH 069/495] [CMake] Option to control whether shared/static library is installed Currently it's only possible to control whether shared or static library build of libc++, libc++abi and libunwind is enabled or disabled and whether to install everything we've built or not. However, it'd be useful to have more fine grained control, e.g. when static libraries are merged together into libc++.a we don't need to install libc++abi.a and libunwind.a. This change adds this option. Differential Revision: https://reviews.llvm.org/D49573 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337867 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 6 ++++++ lib/CMakeLists.txt | 17 ++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 549be42e2..29357b088 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,12 @@ set(LIBCXX_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING "Define suffix of library directory name (32/64)") option(LIBCXX_INSTALL_HEADERS "Install the libc++ headers." ON) option(LIBCXX_INSTALL_LIBRARY "Install the libc++ library." ON) +cmake_dependent_option(LIBCXX_INSTALL_STATIC_LIBRARY + "Install the static libc++ library." ON + "LIBCXX_ENABLE_STATIC;LIBCXX_INSTALL_LIBRARY" OFF) +cmake_dependent_option(LIBCXX_INSTALL_SHARED_LIBRARY + "Install the shared libc++ library." ON + "LIBCXX_ENABLE_SHARED;LIBCXX_INSTALL_LIBRARY" OFF) option(LIBCXX_INSTALL_SUPPORT_HEADERS "Install libc++ support headers." ON) cmake_dependent_option(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY "Install libc++experimental.a" ON diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 5ac691a75..5cdf1b868 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -220,8 +220,6 @@ set_target_properties(cxx_objects COMPILE_FLAGS "${LIBCXX_COMPILE_FLAGS}" ) -set(LIBCXX_TARGETS) - # Build the shared library. if (LIBCXX_ENABLE_SHARED) add_library(cxx_shared SHARED $) @@ -236,7 +234,10 @@ if (LIBCXX_ENABLE_SHARED) VERSION "${LIBCXX_ABI_VERSION}.0" SOVERSION "${LIBCXX_ABI_VERSION}" ) - list(APPEND LIBCXX_TARGETS "cxx_shared") + list(APPEND LIBCXX_BUILD_TARGETS "cxx_shared") + if (LIBCXX_INSTALL_SHARED_LIBRARY) + list(APPEND LIBCXX_INSTALL_TARGETS "cxx_shared") + endif() if(WIN32 AND NOT MINGW AND NOT "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") # Since we most likely do not have a mt.exe replacement, disable the # manifest bundling. This allows a normal cmake invocation to pass which @@ -256,8 +257,10 @@ if (LIBCXX_ENABLE_STATIC) LINK_FLAGS "${LIBCXX_LINK_FLAGS}" OUTPUT_NAME "c++" ) - - list(APPEND LIBCXX_TARGETS "cxx_static") + list(APPEND LIBCXX_BUILD_TARGETS "cxx_static") + if (LIBCXX_INSTALL_STATIC_LIBRARY) + list(APPEND LIBCXX_INSTALL_TARGETS "cxx_static") + endif() # Attempt to merge the libc++.a archive and the ABI library archive into one. if (LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY) set(MERGE_ARCHIVES_SEARCH_PATHS "") @@ -286,7 +289,7 @@ if (LIBCXX_ENABLE_STATIC) endif() # Add a meta-target for both libraries. -add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_TARGETS}) +add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_BUILD_TARGETS}) if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) file(GLOB LIBCXX_EXPERIMENTAL_SOURCES ../src/experimental/*.cpp) @@ -362,7 +365,7 @@ if (LIBCXX_INSTALL_LIBRARY) if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY) set(experimental_lib cxx_experimental) endif() - install(TARGETS ${LIBCXX_TARGETS} ${experimental_lib} + install(TARGETS ${LIBCXX_INSTALL_TARGETS} ${experimental_lib} LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx ) -- GitLab From d2e2a0206e8134854b29f672c773657d2fca595e Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 25 Jul 2018 01:55:25 +0000 Subject: [PATCH 070/495] Mark as complete git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337879 91177308-0d34-0410-b5e6-96231b3b80d8 --- www/cxx2a_status.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/cxx2a_status.html b/www/cxx2a_status.html index 6b2d29e5d..fc69b296e 100644 --- a/www/cxx2a_status.html +++ b/www/cxx2a_status.html @@ -72,7 +72,7 @@ P0767R1CWGDeprecate PODAlbuquerqueComplete7.0 P0768R1CWGLibrary Support for the Spaceship (Comparison) OperatorAlbuquerque P0777R1LWGTreating Unnecessary decayAlbuquerqueComplete7.0 - P0122R7LWG<span>JacksonvilleIn Progress + P0122R7LWG<span>JacksonvilleComplete7.0 P0355R7LWGExtending chrono to Calendars and Time ZonesJacksonville P0551R3LWGThou Shalt Not Specialize std Function Templates!Jacksonville P0753R2LWGManipulators for C++ Synchronized Buffered OstreamJacksonville @@ -222,7 +222,7 @@ -

Last Updated: 11-Jun-2018

+

Last Updated: 23-Jul-2018

-- GitLab From 88dfb6d532a5ef6216a1d90c30dcea026c49615e Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 02:53:53 +0000 Subject: [PATCH 071/495] Add design docs for upcoming file_time_type change. In upcoming changes to filesystem I plan to change file_time_type to use __int128_t as its underlying representation, in order to allow it to have a range and resolution at least that of the timespec struct. There was some pushback against this decision, so I drafted a document explaining the problems, potential solutions, and the rational for the decision. However, it's probably easier to let people read the generated HTML rather than the raw restructured text. For this reason I'm commiting the design documents before hand, so they can be available during any subsequent discussion or code review. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337880 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/DesignDocs/FileTimeType.rst | 493 +++++++++++++++++++++++++++++++ docs/Makefile.sphinx | 2 +- docs/index.rst | 1 + 3 files changed, 495 insertions(+), 1 deletion(-) create mode 100644 docs/DesignDocs/FileTimeType.rst diff --git a/docs/DesignDocs/FileTimeType.rst b/docs/DesignDocs/FileTimeType.rst new file mode 100644 index 000000000..83d5fed16 --- /dev/null +++ b/docs/DesignDocs/FileTimeType.rst @@ -0,0 +1,493 @@ +============== +File Time Type +============== + +.. contents:: + :local: + +.. _file-time-type-motivation: + +Motivation +========== + +The filesystem library provides interfaces for getting and setting the last +write time of a file or directory. The interfaces use the ``file_time_type`` +type, which is a specialization of ``chrono::time_point`` for the +"filesystem clock". According to [fs.filesystem.syn] + + trivial-clock is an implementation-defined type that satisfies the + Cpp17TrivialClock requirements ([time.clock.req]) and that is capable of + representing and measuring file time values. Implementations should ensure + that the resolution and range of file_­time_­type reflect the operating + system dependent resolution and range of file time values. + + +On POSIX systems, file times are represented using the ``timespec`` struct, +which is defined as follows: + +.. code-block:: cpp + + struct timespec { + time_t tv_sec; + long tv_nsec; + }; + +To represent the range and resolution of ``timespec``, we need to (A) have +nanosecond resolution, and (B) use more than 64 bits (assuming a 64 bit ``time_t``). + +As the standard requires us to use the ``chrono`` interface, we have to define +our own filesystem clock which specifies the period and representation of +the time points and duration it provides. It will look like this: + +.. code-block:: cpp + + struct _FilesystemClock { + using period = nano; + using rep = TBD; // What is this? + + using duration = chrono::duration; + using time_point = chrono::time_point<_FilesystemClock>; + + // ... // + }; + + using file_time_type = _FilesystemClock::time_point; + + +To get nanosecond resolution, we simply define ``period`` to be ``std::nano``. +But what type can we use as the arithmetic representation that is capable +of representing the range of the ``timespec`` struct? + +Problems To Consider +==================== + +Before considering solutions, lets consider the problems they should solve, +and how important solving those problems are: + + +Having a Smaller Range than ``timespec`` +---------------------------------------- + +One solution to the range problem is to simply reduce the resolution of +``file_time_type`` to be less than that of nanoseconds. This is what libc++'s +initial implementation of ``file_time_type`` did; it's also what +``std::system_clock`` does. As a result, it can represent time points about +292 thousand years on either side of the epoch, as opposed to only 292 years +at nanosecond resolution. + +``timespec`` can represent time points +/- 292 billion years from the epoch +(just in case you needed a time point 200 billion years before the big bang, +and with nanosecond resolution). + +To get the same range, we would need to drop our resolution to that of seconds +to come close to having the same range. + +This begs the question, is the range problem "really a problem"? Sane usages +of file time stamps shouldn't exceed +/- 300, so should we care to support it? + +I believe the answer is yes. We're not designing the filesystem time API, we're +providing glorified C++ wrappers for it. If the underlying API supports +a value, then we should too. Our wrappers should not place artificial restrictions +on users that are not present in the underlying filesystem. + +Additionally, having a smaller range that the underlying filesystem forces the +implementation to report ``value_too_large`` errors when it encounters a time +point that it can't represent. This can cause the call to ``last_write_time`` +to throw in cases where the user was confident the call should succeed. (See below) + + +.. code-block:: cpp + + #include + using namespace std::filesystem; + + // Set the times using the system interface. + void set_file_times(const char* path, struct timespec ts) { + timespec both_times[2]; + both_times[0] = ts; + both_times[1] = ts; + int result = ::utimensat(AT_FDCWD, path, both_times, 0); + assert(result != -1); + } + + // Called elsewhere to set the file time to something insane, and way + // out of the 300 year range we might expect. + void some_bad_persons_code() { + struct timespec new_times; + new_times.tv_sec = numeric_limits::max(); + new_times.tv_nsec = 0; + set_file_times("/tmp/foo", new_times); // OK, supported by most FSes + } + + int main() { + path p = "/tmp/foo"; + file_status st = status(p); + if (!exists(st) || !is_regular_file(st)) + return 1; + if ((st.permissions() & perms::others_read) == perms::none) + return 1; + // It seems reasonable to assume this call should succeed. + file_time_type tp = last_write_time(p); // BAD! Throws value_too_large. + } + + +Having a Smaller Resolution than ``timespec`` +--------------------------------------------- + +As mentioned in the previous section, one way to solve the range problem +is by reducing the resolution, and matching the range of ``timespec`` using a +64 bit representation requires limiting the resolution to seconds. + +So we might ask: Do users "need" nanosecond precision? Is seconds not good enough? +I limit my consideration of the point to this: Why was it not good enough for +the underlying system interfaces? If it wasn't good enough for them, then it +isn't good enough for us. Our job is to match the filesystems range and +representation, not design it. + + +Having a Larger Range than ``timespec`` +---------------------------------------- + +We also should consider the opposite problem of having ``file_time_type`` +be able to represent a larger range than that of ``timespec``. At least in +this case ``last_write_time`` can be used to get and set all possible values +supported by the underlying filesystem; meaning ``last_write_time(p)`` will +never throw a overflow error. + +However, this introduces a new problem, where users are allowed to create time +points beyond what the filesystem can represent. Two particular values are +``file_time_type::min()`` and ``file_time_type::max()``. As such the following +code would throw: + +.. code-block:: cpp + + void test() { + last_write_time("/tmp/foo", file_time_type::max()); // Throws + last_write_time("/tmp/foo", file_time_type::min()); // Throws. + } + +Apart from cases explicitly using ``min`` and ``max``, I don't see users taking +a valid time point, adding a couple hundred billions of years to it in error, +and then trying to update a files write time with that value very often. + +Compared to having a smaller range, this problem seems preferable. At least +now we can represent any time point the filesystem can, so users won't be forced +to revert back to system interfaces to avoid limitations in the C++ STL. + +I posit that we should only consider this concern *after* we have something +with at least the same range and resolution of the underlying filesystem. The +latter two problems are much more important to solve. + +Potential Solutions And Their Complications +=========================================== + +Source Code Portability Across Implementations +----------------------------------------------- + +As we've discussed, ``file_time_type`` needs a representation that uses more +than 64 bits. The possible solutions include using ``__int128_t``, emulating a +128 bit integer using a class, or potentially defining a ``timespec`` like +arithmetic type. All three will solve allow us to, at minimum, match the range +and resolution, and the last one might even allow us to match them exactly. + +But when considering these potential solutions, we need to consider more than +just the values they can represent. We need to consider the effect they will have +on users and their code. For example, each of them breaks the following code +in some way: + +.. code-block:: cpp + + // Bug caused by an unexpected 'rep' type returned by count. + void print_time(path p) { + // __int128_t doesn't have streaming operators, and neither would our + // custom arithmetic types. + cout << last_write_time(p).time_since_epoch().count() << endl; + } + + // Overflow during creation bug. + file_time_type timespec_to_file_time_type(struct timespec ts) { + // woops! chrono::seconds and chrono::nanoseconds use a 64 bit representation + // this may overflow before it's converted to a file_time_type. + auto dur = seconds(ts.tv_sec) + nanoseconds(ts.tv_nsec); + return file_time_type(dur); + } + + file_time_type correct_timespec_to_file_time_type(struct timespec ts) { + // This is the correct version of the above example, where we + // avoid using the chrono typedefs as their not sufficient. + // Can we expect users to avoid this bug? + using fs_seconds = chrono::duration; + using fs_nanoseconds = chrono::duration; + auto dur = fs_seconds(ts.tv_sec) + fs_nanoseconds(tv.tv_nsec); + return file_time_type(dur); + } + + // Implicit truncation during conversion bug. + intmax_t get_time_in_seconds(path p) { + using fs_seconds = duration; + auto tp = last_write_time(p); + + // This works with truncation for __int128_t, but what does it do for + // our custom arithmetic types. + return duration_cast().count(); + } + + +Each of the above examples would require a user to adjust their filesystem code +to the particular eccentricities of the representation type, hopefully in +such a way that the code is still portable across implementations. + +It seems like at least some of the above issues are unavoidable, no matter +what representation we choose. But some representations may be quirkier than +others, and, as I'll argue later, using an actual arithmetic type (``__int128_t``) +provides the least aberrant behavior. + + +Chrono and ``timespec`` Emulation. +---------------------------------- + +One of the options we've considered is using something akin to ``timespec`` +to represent the ``file_time_type``. It only seems natural seeing as that's +what the underlying system uses, and because it might allow us to match +the range and resolution exactly. But would it work with chrono? And could +it still act at all like a ``timespec`` struct? + +For ease of consideration, lets consider the what the implementation might +look like. + +.. code-block:: cpp + + struct fs_timespec_rep { + fs_timespec_rep(long long v) + : tv_sec(v / nano::den), tv_nsec(v % nano::den) + { } + private: + time_t tv_sec; + long tv_nsec; + }; + bool operator==(fs_timespec_rep, fs_timespec_rep); + fs_int128_rep operator+(fs_timespec_rep, fs_timespec_rep); + // ... arithmetic operators ... // + +The first thing to notice is that we can't construct ``fs_timespec_rep`` like +a ``timespec`` by passing ``{secs, nsecs}``. Instead we're limited to constructing +it from a single 64 bit integer. + +We also can't allow the user to inspect the ``tv_sec`` or ``tv_nsec`` values +directly. A ``chrono::duration`` represents its value as a tick period and a +number of ticks stored using ``rep``. The representation is unaware of the +tick period its being used to represent, but ``timespec`` is setup to assume a +nanosecond tick period. That's the only case where the names of the ``tv_sec`` +and ``tv_nsec`` members matches the values they store. + +When we convert a nanosecond duration to a seconds, ``fs_timespec_rep`` +will be using ``tv_sec`` to represent the number of giga seconds, and ``tv_nsec`` +the remaining seconds. Lets consider how this might cause a bug were users allowed +to manipulate the fields directly. + +.. code-block:: cpp + + template + timespec convert_to_timespec(duration dur) { + fs_timespec_rep rep = dur.count(); + return {rep.tv_sec, rep.tv_nsec}; // Oops! Period may not be nanoseconds. + } + + template + Duration convert_to_duration(timespec ts) { + Duration dur({ts.tv_sec, ts.tv_nsec}); // Oops! Period may not be nanoseconds. + return file_time_type(dur); + file_time_type tp = last_write_time(p); + auto dur = + } + + time_t extract_seconds(file_time_type tp) { + // Converting to seconds is a silly bug, but I could see it happening. + using SecsT = chrono::duration>; + auto secs = duration_cast(tp.time_since_epoch()); + // tv_sec is now representing gigaseconds. + return secs.count().tv_sec; // Oops! + } + +However, despite ``fs_timespec_rep`` not being usable in any manner resembling +``timespec``, it still might buy us our goal of matching its range exactly, +right? + +Sort of. Chrono provides a specialization point which specifies the minimum +and maximum values for a custom representation. It looks like this: + +.. code-block:: cpp + + template <> + struct duration_values { + static fs_timespec_rep zero(); + static fs_timespec_rep min(); + static fs_timespec_rep max() { // assume friendship. + fs_timespec_rep val; + val.tv_sec = numeric_limits::max(); + val.tv_nsec = nano::den - 1; + return val; + } + }; + +Notice that ``duration_values`` doesn't tell the representation what tick period +it's actually representing. This would indeed correctly limit the range of +``duration`` to exactly that of ``timespec``. But +nanoseconds isn't the only tick period it will be used to represent. For example: + +.. code-block:: cpp + + void test() { + using rep = file_time_type::rep; + using fs_nsec = duration; + using fs_sec = duration; + fs_nsec nsecs(fs_seconds::max()); // Truncates + } + +Though the above example may appear silly, I it follows from the incorrect +notion that using a ``timespec`` rep in chrono actually makes it act as if it +were an actual ``timespec``. + +Interactions with 32 bit ``time_t`` +----------------------------------- + +Up until now we've only be considering cases where ``time_t`` is 64 bits, but what +about 32 bit systems/builds where ``time_t`` is 32 bits? (this is the common case +for 32 bit builds). + +When ``time_t`` is 32 bits, we can implement ``file_time_type`` simply using 64-bit +``long long``. There is no need to get either ``__int128_t`` or ``timespec`` emulation +involved. And nor should we, as it would suffer from the numerous complications +described by this paper. + +Obviously our implementation for 32-bit builds should act as similarly to the +64-bit build as possible. Code which compiles in one, should compile in the other. +This consideration is important when choosing between ``__int128_t`` and +emulating ``timespec``. The solution which provides the most uniformity is +the preferable one, with the least eccentricity is the preferable one. + +Summary +======= + +The ``file_time_type`` time point is used to represent the write times for files. +Its job is to act as part of a C++ wrapper for less ideal system interfaces. The +underlying filesystem uses the ``timespec`` struct for the same purpose. + +However, the initial implementation of ``file_time_type`` could not represent +either the range or resolution of ``timespec``, making it unsuitable. Fixing +this requires an implementation which uses more than 64 bits to store the +time point. + +We primarily considered two solutions: Using ``__int128_t`` and using a +arithmetic emulation of ``timespec``. Each has its pros and cons, and both +come with more than one complication. + +The Potential Solutions +----------------------- + +``long long`` - The Status Quo +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Pros: + +* As a type ``long long`` places the nicest with others: + + * It works with streaming operators and other library entities which support + builtin integer types, but don't support ``__int128_t``. + * Its the representation used by chrono's ``nanosecond`` and ``second`` typedefs. + +Cons: + +* It cannot provide the same resolution as ``timespec`` unless we limit it + to a range of +/- 300 years from the epoch. +* It cannot provide the same range as ``timespec`` unless we limit its resolution + to seconds. +* ``last_write_time`` has to report an error when the time reported by the filesystem + is unrepresentable. + +__int128_t +~~~~~~~~~~~ + +Pros: + +* It is an integer type. +* It makes the implementation simply and efficient. +* Acts exactly like other arithmetic types. +* Can be implicitly converted to a builtin integer type by the user. + + * This is important for doing things like: + + .. code-block:: cpp + + void c_interface_using_time_t(const char* p, time_t); + + void foo(path p) { + file_time_type tp = last_write_time(p); + time_t secs = duration_cast(tp.time_since_epoch()).count(); + c_interface_using_time_t(p.c_str(), secs); + } + +Cons: + +* It isn't always available (but on 64 bit machines, it normally is). +* It causes ``file_time_type`` to have a larger range than ``timespec``. +* It doesn't always act the same as other builtin integer types. For example + with ``cout`` or ``to_string``. +* Allows implicit truncation to 64 bit integers. +* It can be implicitly converted to a builtin integer type by the user, + truncating its value. + +Arithmetic ``timespec`` Emulation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Pros: + +* It has the exact same range and resolution of ``timespec`` when representing + a nanosecond tick period. +* It's always available, unlike ``__int128_t``. + +Cons: + +* It has a larger range when representing any period longer than a nanosecond. +* Doesn't actually allow users to use it like a ``timespec``. +* The required representation of using ``tv_sec`` to store the giga tick count + and ``tv_nsec`` to store the remainder adds nothing over a 128 bit integer, + but complicates a lot. +* It isn't a builtin integer type, and can't be used anything like one. +* Chrono can be made to work with it, but not nicely. +* Emulating arithmetic classes come with their own host of problems regarding + overload resolution (Each operator needs three SFINAE constrained versions of + it in order to act like builtin integer types). +* It offers little over simply using ``__int128_t``. +* It acts the most differently than implementations using an actual integer type, + which has a high chance of breaking source compatibility. + + +Selected Solution - Using ``__int128_t`` +========================================= + +The solution I selected for libc++ is using ``__int128_t`` when available, +and otherwise falling back to using ``long long`` with nanosecond precision. + +When ``__int128_t`` is available, or when ``time_t`` is 32-bits, the implementation +provides same resolution and a greater range than ``timespec``. Otherwise +it still provides the same resolution, but is limited to a range of +/- 300 +years. This final case should be rather rare, as ``__int128_t`` +is normally available in 64-bit builds, and ``time_t`` is normally 32-bits +during 32-bit builds. + +Although falling back to ``long long`` and nanosecond precision is less than +ideal, it also happens to be the implementation provided by both libstdc++ +and MSVC. (So that makes it better, right?) + +Although the ``timespec`` emulation solution is feasible and would largely +do what we want, it comes with too many complications, potential problems +and discrepancies when compared to "normal" chrono time points and durations. + +An emulation of a builtin arithmetic type using a class is never going to act +exactly the same, and the difference will be felt by users. It's not reasonable +to expect them to tolerate and work around these differences. And once +we commit to an ABI it will be too late to change. Committing to this seems +risky. + +Therefore, ``__int128_t`` seems like the better solution. diff --git a/docs/Makefile.sphinx b/docs/Makefile.sphinx index ae37a34b5..a34f0cc0b 100644 --- a/docs/Makefile.sphinx +++ b/docs/Makefile.sphinx @@ -5,7 +5,7 @@ # out-of-tree builds. # You can set these variables from the command line. -SPHINXOPTS = -n -W +SPHINXOPTS = -n -W -v SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build diff --git a/docs/index.rst b/docs/index.rst index 3526b4721..e4b3a879d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -134,6 +134,7 @@ Design Documents DesignDocs/ABIVersioning DesignDocs/VisibilityMacros DesignDocs/ThreadingSupportAPI + DesignDocs/FileTimeType * ` design `_ * ` design `_ -- GitLab From 0fbaa11dd3b95c9798e3e5bc2b20c4f40640e6d6 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 03:31:48 +0000 Subject: [PATCH 072/495] Ensure path::iterator and PathParser share the same enumeration values. To avoid exposing implementation details, path::iterator and PathParser both implicitly used the same set of values to represent the state, but they were defined twice. This could have lead to a mismatch occuring. This patch moves all of the parser state values into the filesystem header and changes PathParser to use those value to avoid this. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337883 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/experimental/filesystem | 27 ++++++++++++++-------- src/experimental/filesystem/operations.cpp | 21 ++++++++--------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/include/experimental/filesystem b/include/experimental/filesystem index 9699699c7..1f6d1ab4d 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -1037,7 +1037,7 @@ public: _LIBCPP_INLINE_VISIBILITY path extension() const { return string_type(__extension()); } // query - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool empty() const _NOEXCEPT { return __pn_.empty(); } _LIBCPP_INLINE_VISIBILITY bool has_root_name() const { return !__root_name().empty(); } @@ -1169,6 +1169,17 @@ u8path(_InputIt __f, _InputIt __l) { class _LIBCPP_TYPE_VIS path::iterator { +public: + enum _ParserState : unsigned char { + _Singular, + _BeforeBegin, + _InRootName, + _InRootDir, + _InFilenames, + _InTrailingSep, + _AtEnd + }; + public: typedef bidirectional_iterator_tag iterator_category; @@ -1178,10 +1189,11 @@ public: typedef const path& reference; typedef void __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator + public: _LIBCPP_INLINE_VISIBILITY iterator() : __stashed_elem_(), __path_ptr_(nullptr), - __entry_(), __state_(__singular) {} + __entry_(), __state_(_Singular) {} iterator(const iterator&) = default; ~iterator() = default; @@ -1200,9 +1212,9 @@ public: _LIBCPP_INLINE_VISIBILITY iterator& operator++() { - _LIBCPP_ASSERT(__state_ != __singular, + _LIBCPP_ASSERT(__state_ != _Singular, "attempting to increment a singular iterator"); - _LIBCPP_ASSERT(__state_ != __at_end, + _LIBCPP_ASSERT(__state_ != _AtEnd, "attempting to increment the end iterator"); return __increment(); } @@ -1216,7 +1228,7 @@ public: _LIBCPP_INLINE_VISIBILITY iterator& operator--() { - _LIBCPP_ASSERT(__state_ != __singular, + _LIBCPP_ASSERT(__state_ != _Singular, "attempting to decrement a singular iterator"); _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(), "attempting to decrement the begin iterator"); @@ -1233,9 +1245,6 @@ public: private: friend class path; - static constexpr unsigned char __singular = 0; - static constexpr unsigned char __at_end = 6; - inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&, const iterator&); @@ -1245,7 +1254,7 @@ private: path __stashed_elem_; const path* __path_ptr_; path::__string_view __entry_; - unsigned char __state_; + _ParserState __state_; }; inline _LIBCPP_INLINE_VISIBILITY diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index dd805193b..089e34b20 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -57,12 +57,12 @@ using PosPtr = path::value_type const*; struct PathParser { enum ParserState : unsigned char { // Zero is a special sentinel value used by default constructed iterators. - PS_BeforeBegin = 1, - PS_InRootName, - PS_InRootDir, - PS_InFilenames, - PS_InTrailingSep, - PS_AtEnd + PS_BeforeBegin = path::iterator::_BeforeBegin, + PS_InRootName = path::iterator::_InRootName, + PS_InRootDir = path::iterator::_InRootDir, + PS_InFilenames = path::iterator::_InFilenames, + PS_InTrailingSep = path::iterator::_InTrailingSep, + PS_AtEnd = path::iterator::_AtEnd }; const string_view_t Path; @@ -1548,7 +1548,7 @@ path::iterator path::begin() const auto PP = PathParser::CreateBegin(__pn_); iterator it; it.__path_ptr_ = this; - it.__state_ = PP.State; + it.__state_ = static_cast(PP.State); it.__entry_ = PP.RawEntry; it.__stashed_elem_.__assign_view(*PP); return it; @@ -1557,16 +1557,15 @@ path::iterator path::begin() const path::iterator path::end() const { iterator it{}; - it.__state_ = PathParser::PS_AtEnd; + it.__state_ = path::iterator::_AtEnd; it.__path_ptr_ = this; return it; } path::iterator& path::iterator::__increment() { - static_assert(__at_end == PathParser::PS_AtEnd, ""); PathParser PP(__path_ptr_->native(), __entry_, __state_); ++PP; - __state_ = PP.State; + __state_ = static_cast<_ParserState>(PP.State); __entry_ = PP.RawEntry; __stashed_elem_.__assign_view(*PP); return *this; @@ -1575,7 +1574,7 @@ path::iterator& path::iterator::__increment() { path::iterator& path::iterator::__decrement() { PathParser PP(__path_ptr_->native(), __entry_, __state_); --PP; - __state_ = PP.State; + __state_ = static_cast<_ParserState>(PP.State); __entry_ = PP.RawEntry; __stashed_elem_.__assign_view(*PP); return *this; -- GitLab From 2493db4b2686263c0cfb1dab49c9fb1f218164ff Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 03:41:31 +0000 Subject: [PATCH 073/495] Make explicitly require C++11. Previously the didn't guard its contents in any dialect. However, the implementation implicitly requires at least C++11, and the tests have always been marked unsupported in C++03. This patch puts a header guard around the contents to avoid exposing them before C++11. Additionally, it replaces all of the usages of _NOEXCEPT or _LIBCPP_CONSTEXPR with the keyword directly, since we can expect the compiler to implement those by now. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337884 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/experimental/filesystem | 326 +++++++++--------- .../filesystem/filesystem_common.h | 2 - .../fs.req.macros/feature_macro.pass.cpp | 11 +- 3 files changed, 173 insertions(+), 166 deletions(-) diff --git a/include/experimental/filesystem b/include/experimental/filesystem index 1f6d1ab4d..060c7e033 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -16,15 +16,15 @@ class path; - void swap(path& lhs, path& rhs) _NOEXCEPT; - size_t hash_value(const path& p) _NOEXCEPT; + void swap(path& lhs, path& rhs) noexcept; + size_t hash_value(const path& p) noexcept; - bool operator==(const path& lhs, const path& rhs) _NOEXCEPT; - bool operator!=(const path& lhs, const path& rhs) _NOEXCEPT; - bool operator< (const path& lhs, const path& rhs) _NOEXCEPT; - bool operator<=(const path& lhs, const path& rhs) _NOEXCEPT; - bool operator> (const path& lhs, const path& rhs) _NOEXCEPT; - bool operator>=(const path& lhs, const path& rhs) _NOEXCEPT; + bool operator==(const path& lhs, const path& rhs) noexcept; + bool operator!=(const path& lhs, const path& rhs) noexcept; + bool operator< (const path& lhs, const path& rhs) noexcept; + bool operator<=(const path& lhs, const path& rhs) noexcept; + bool operator> (const path& lhs, const path& rhs) noexcept; + bool operator>=(const path& lhs, const path& rhs) noexcept; path operator/ (const path& lhs, const path& rhs); @@ -96,88 +96,88 @@ void copy_symlink(const path& existing_symlink, const path& new_symlink); void copy_symlink(const path& existing_symlink, const path& new_symlink, - error_code& ec) _NOEXCEPT; + error_code& ec) noexcept; bool create_directories(const path& p); bool create_directories(const path& p, error_code& ec); bool create_directory(const path& p); - bool create_directory(const path& p, error_code& ec) _NOEXCEPT; + bool create_directory(const path& p, error_code& ec) noexcept; bool create_directory(const path& p, const path& attributes); bool create_directory(const path& p, const path& attributes, - error_code& ec) _NOEXCEPT; + error_code& ec) noexcept; void create_directory_symlink(const path& to, const path& new_symlink); void create_directory_symlink(const path& to, const path& new_symlink, - error_code& ec) _NOEXCEPT; + error_code& ec) noexcept; void create_hard_link(const path& to, const path& new_hard_link); void create_hard_link(const path& to, const path& new_hard_link, - error_code& ec) _NOEXCEPT; + error_code& ec) noexcept; void create_symlink(const path& to, const path& new_symlink); void create_symlink(const path& to, const path& new_symlink, - error_code& ec) _NOEXCEPT; + error_code& ec) noexcept; path current_path(); path current_path(error_code& ec); void current_path(const path& p); - void current_path(const path& p, error_code& ec) _NOEXCEPT; + void current_path(const path& p, error_code& ec) noexcept; - bool exists(file_status s) _NOEXCEPT; + bool exists(file_status s) noexcept; bool exists(const path& p); - bool exists(const path& p, error_code& ec) _NOEXCEPT; + bool exists(const path& p, error_code& ec) noexcept; bool equivalent(const path& p1, const path& p2); - bool equivalent(const path& p1, const path& p2, error_code& ec) _NOEXCEPT; + bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept; uintmax_t file_size(const path& p); - uintmax_t file_size(const path& p, error_code& ec) _NOEXCEPT; + uintmax_t file_size(const path& p, error_code& ec) noexcept; uintmax_t hard_link_count(const path& p); - uintmax_t hard_link_count(const path& p, error_code& ec) _NOEXCEPT; + uintmax_t hard_link_count(const path& p, error_code& ec) noexcept; - bool is_block_file(file_status s) _NOEXCEPT; + bool is_block_file(file_status s) noexcept; bool is_block_file(const path& p); - bool is_block_file(const path& p, error_code& ec) _NOEXCEPT; + bool is_block_file(const path& p, error_code& ec) noexcept; - bool is_character_file(file_status s) _NOEXCEPT; + bool is_character_file(file_status s) noexcept; bool is_character_file(const path& p); - bool is_character_file(const path& p, error_code& ec) _NOEXCEPT; + bool is_character_file(const path& p, error_code& ec) noexcept; - bool is_directory(file_status s) _NOEXCEPT; + bool is_directory(file_status s) noexcept; bool is_directory(const path& p); - bool is_directory(const path& p, error_code& ec) _NOEXCEPT; + bool is_directory(const path& p, error_code& ec) noexcept; bool is_empty(const path& p); - bool is_empty(const path& p, error_code& ec) _NOEXCEPT; + bool is_empty(const path& p, error_code& ec) noexcept; - bool is_fifo(file_status s) _NOEXCEPT; + bool is_fifo(file_status s) noexcept; bool is_fifo(const path& p); - bool is_fifo(const path& p, error_code& ec) _NOEXCEPT; + bool is_fifo(const path& p, error_code& ec) noexcept; - bool is_other(file_status s) _NOEXCEPT; + bool is_other(file_status s) noexcept; bool is_other(const path& p); - bool is_other(const path& p, error_code& ec) _NOEXCEPT; + bool is_other(const path& p, error_code& ec) noexcept; - bool is_regular_file(file_status s) _NOEXCEPT; + bool is_regular_file(file_status s) noexcept; bool is_regular_file(const path& p); - bool is_regular_file(const path& p, error_code& ec) _NOEXCEPT; + bool is_regular_file(const path& p, error_code& ec) noexcept; - bool is_socket(file_status s) _NOEXCEPT; + bool is_socket(file_status s) noexcept; bool is_socket(const path& p); - bool is_socket(const path& p, error_code& ec) _NOEXCEPT; + bool is_socket(const path& p, error_code& ec) noexcept; - bool is_symlink(file_status s) _NOEXCEPT; + bool is_symlink(file_status s) noexcept; bool is_symlink(const path& p); - bool is_symlink(const path& p, error_code& ec) _NOEXCEPT; + bool is_symlink(const path& p, error_code& ec) noexcept; file_time_type last_write_time(const path& p); - file_time_type last_write_time(const path& p, error_code& ec) _NOEXCEPT; + file_time_type last_write_time(const path& p, error_code& ec) noexcept; void last_write_time(const path& p, file_time_type new_time); void last_write_time(const path& p, file_time_type new_time, - error_code& ec) _NOEXCEPT; + error_code& ec) noexcept; void permissions(const path& p, perms prms, perm_options opts=perm_options::replace); @@ -197,27 +197,27 @@ path relative(const path& p, const path& base, error_code& ec); bool remove(const path& p); - bool remove(const path& p, error_code& ec) _NOEXCEPT; + bool remove(const path& p, error_code& ec) noexcept; uintmax_t remove_all(const path& p); uintmax_t remove_all(const path& p, error_code& ec); void rename(const path& from, const path& to); - void rename(const path& from, const path& to, error_code& ec) _NOEXCEPT; + void rename(const path& from, const path& to, error_code& ec) noexcept; void resize_file(const path& p, uintmax_t size); - void resize_file(const path& p, uintmax_t size, error_code& ec) _NOEXCEPT; + void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept; space_info space(const path& p); - space_info space(const path& p, error_code& ec) _NOEXCEPT; + space_info space(const path& p, error_code& ec) noexcept; file_status status(const path& p); - file_status status(const path& p, error_code& ec) _NOEXCEPT; + file_status status(const path& p, error_code& ec) noexcept; - bool status_known(file_status s) _NOEXCEPT; + bool status_known(file_status s) noexcept; file_status symlink_status(const path& p); - file_status symlink_status(const path& p, error_code& ec) _NOEXCEPT; + file_status symlink_status(const path& p, error_code& ec) noexcept; path temp_directory_path(); path temp_directory_path(error_code& ec); @@ -254,6 +254,8 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> +#ifndef _LIBCPP_CXX03_LANG + #define __cpp_lib_experimental_filesystem 201406 _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM @@ -310,19 +312,19 @@ enum class _LIBCPP_ENUM_VIS perms : unsigned }; _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR perms operator&(perms _LHS, perms _RHS) +inline constexpr perms operator&(perms _LHS, perms _RHS) { return static_cast(static_cast(_LHS) & static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR perms operator|(perms _LHS, perms _RHS) +inline constexpr perms operator|(perms _LHS, perms _RHS) { return static_cast(static_cast(_LHS) | static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR perms operator^(perms _LHS, perms _RHS) +inline constexpr perms operator^(perms _LHS, perms _RHS) { return static_cast(static_cast(_LHS) ^ static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR perms operator~(perms _LHS) +inline constexpr perms operator~(perms _LHS) { return static_cast(~static_cast(_LHS)); } _LIBCPP_INLINE_VISIBILITY @@ -345,19 +347,19 @@ enum class _LIBCPP_ENUM_VIS perm_options : unsigned char { }; _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR perm_options operator&(perm_options _LHS, perm_options _RHS) +inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) { return static_cast(static_cast(_LHS) & static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR perm_options operator|(perm_options _LHS, perm_options _RHS) +inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) { return static_cast(static_cast(_LHS) | static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR perm_options operator^(perm_options _LHS, perm_options _RHS) +inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) { return static_cast(static_cast(_LHS) ^ static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR perm_options operator~(perm_options _LHS) +inline constexpr perm_options operator~(perm_options _LHS) { return static_cast(~static_cast(_LHS)); } _LIBCPP_INLINE_VISIBILITY @@ -388,19 +390,19 @@ enum class _LIBCPP_ENUM_VIS copy_options : unsigned short }; _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR copy_options operator&(copy_options _LHS, copy_options _RHS) +inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) { return static_cast(static_cast(_LHS) & static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR copy_options operator|(copy_options _LHS, copy_options _RHS) +inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) { return static_cast(static_cast(_LHS) | static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR copy_options operator^(copy_options _LHS, copy_options _RHS) +inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) { return static_cast(static_cast(_LHS) ^ static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR copy_options operator~(copy_options _LHS) +inline constexpr copy_options operator~(copy_options _LHS) { return static_cast(~static_cast(_LHS)); } _LIBCPP_INLINE_VISIBILITY @@ -424,19 +426,19 @@ enum class _LIBCPP_ENUM_VIS directory_options : unsigned char }; _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR directory_options operator&(directory_options _LHS, directory_options _RHS) +inline constexpr directory_options operator&(directory_options _LHS, directory_options _RHS) { return static_cast(static_cast(_LHS) & static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR directory_options operator|(directory_options _LHS, directory_options _RHS) +inline constexpr directory_options operator|(directory_options _LHS, directory_options _RHS) { return static_cast(static_cast(_LHS) | static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR directory_options operator^(directory_options _LHS, directory_options _RHS) +inline constexpr directory_options operator^(directory_options _LHS, directory_options _RHS) { return static_cast(static_cast(_LHS) ^ static_cast(_RHS)); } _LIBCPP_INLINE_VISIBILITY -inline _LIBCPP_CONSTEXPR directory_options operator~(directory_options _LHS) +inline constexpr directory_options operator~(directory_options _LHS) { return static_cast(~static_cast(_LHS)); } _LIBCPP_INLINE_VISIBILITY @@ -457,41 +459,41 @@ class _LIBCPP_TYPE_VIS file_status public: // constructors _LIBCPP_INLINE_VISIBILITY - file_status() _NOEXCEPT : file_status(file_type::none) {} + file_status() noexcept : file_status(file_type::none) {} _LIBCPP_INLINE_VISIBILITY explicit file_status(file_type __ft, - perms __prms = perms::unknown) _NOEXCEPT + perms __prms = perms::unknown) noexcept : __ft_(__ft), __prms_(__prms) {} - file_status(const file_status&) _NOEXCEPT = default; - file_status(file_status&&) _NOEXCEPT = default; + file_status(const file_status&) noexcept = default; + file_status(file_status&&) noexcept = default; _LIBCPP_INLINE_VISIBILITY ~file_status() {} - file_status& operator=(const file_status&) _NOEXCEPT = default; - file_status& operator=(file_status&&) _NOEXCEPT = default; + file_status& operator=(const file_status&) noexcept = default; + file_status& operator=(file_status&&) noexcept = default; // observers _LIBCPP_INLINE_VISIBILITY - file_type type() const _NOEXCEPT { + file_type type() const noexcept { return __ft_; } _LIBCPP_INLINE_VISIBILITY - perms permissions() const _NOEXCEPT { + perms permissions() const noexcept { return __prms_; } // modifiers _LIBCPP_INLINE_VISIBILITY - void type(file_type __ft) _NOEXCEPT { + void type(file_type __ft) noexcept { __ft_ = __ft; } _LIBCPP_INLINE_VISIBILITY - void permissions(perms __p) _NOEXCEPT { + void permissions(perms __p) noexcept { __prms_ = __p; } private: @@ -723,7 +725,7 @@ public: typedef char value_type; typedef basic_string string_type; typedef _VSTD::string_view __string_view; - static _LIBCPP_CONSTEXPR value_type preferred_separator = '/'; + static constexpr value_type preferred_separator = '/'; enum class _LIBCPP_ENUM_VIS format : unsigned char { auto_format, @@ -732,12 +734,12 @@ public: }; // constructors and destructor - _LIBCPP_INLINE_VISIBILITY path() _NOEXCEPT {} + _LIBCPP_INLINE_VISIBILITY path() noexcept {} _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {} - _LIBCPP_INLINE_VISIBILITY path(path&& __p) _NOEXCEPT : __pn_(_VSTD::move(__p.__pn_)) {} + _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept : __pn_(_VSTD::move(__p.__pn_)) {} _LIBCPP_INLINE_VISIBILITY - path(string_type&& __s, format = format::auto_format) _NOEXCEPT + path(string_type&& __s, format = format::auto_format) noexcept : __pn_(_VSTD::move(__s)) {} template < @@ -775,20 +777,20 @@ public: } _LIBCPP_INLINE_VISIBILITY - path& operator=(path&& __p) _NOEXCEPT { + path& operator=(path&& __p) noexcept { __pn_ = _VSTD::move(__p.__pn_); return *this; } template _LIBCPP_INLINE_VISIBILITY - path& operator=(string_type&& __s) _NOEXCEPT { + path& operator=(string_type&& __s) noexcept { __pn_ = _VSTD::move(__s); return *this; } _LIBCPP_INLINE_VISIBILITY - path& assign(string_type&& __s) _NOEXCEPT { + path& assign(string_type&& __s) noexcept { __pn_ = _VSTD::move(__s); return *this; } @@ -934,7 +936,7 @@ public: // modifiers _LIBCPP_INLINE_VISIBILITY - void clear() _NOEXCEPT { + void clear() noexcept { __pn_.clear(); } @@ -956,7 +958,7 @@ public: path& replace_extension(const path& __replacement = path()); _LIBCPP_INLINE_VISIBILITY - void swap(path& __rhs) _NOEXCEPT { + void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); } @@ -966,12 +968,12 @@ public: // native format observers _LIBCPP_INLINE_VISIBILITY - const string_type& native() const _NOEXCEPT { + const string_type& native() const noexcept { return __pn_; } _LIBCPP_INLINE_VISIBILITY - const value_type* c_str() const _NOEXCEPT { return __pn_.c_str(); } + const value_type* c_str() const noexcept { return __pn_.c_str(); } _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; } @@ -1021,7 +1023,7 @@ private: public: // compare - _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const _NOEXCEPT { return __compare(__p.__pn_);} + _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept { return __compare(__p.__pn_);} _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const { return __compare(__s); } _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const { return __compare(__s); } _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const { return __compare(__s); } @@ -1038,7 +1040,7 @@ public: // query _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY - bool empty() const _NOEXCEPT { return __pn_.empty(); } + bool empty() const noexcept { return __pn_.empty(); } _LIBCPP_INLINE_VISIBILITY bool has_root_name() const { return !__root_name().empty(); } _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const { return !__root_directory().empty(); } @@ -1111,35 +1113,35 @@ private: }; inline _LIBCPP_INLINE_VISIBILITY -void swap(path& __lhs, path& __rhs) _NOEXCEPT { +void swap(path& __lhs, path& __rhs) noexcept { __lhs.swap(__rhs); } _LIBCPP_FUNC_VIS -size_t hash_value(const path& __p) _NOEXCEPT; +size_t hash_value(const path& __p) noexcept; inline _LIBCPP_INLINE_VISIBILITY -bool operator==(const path& __lhs, const path& __rhs) _NOEXCEPT +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 +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 +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 +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 +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 +bool operator>=(const path& __lhs, const path& __rhs) noexcept { return __lhs.compare(__rhs) >= 0; } inline _LIBCPP_INLINE_VISIBILITY @@ -1294,15 +1296,15 @@ public: } _LIBCPP_INLINE_VISIBILITY - const path& path1() const _NOEXCEPT { return __storage_->__p1_; } + const path& path1() const noexcept { return __storage_->__p1_; } _LIBCPP_INLINE_VISIBILITY - const path& path2() const _NOEXCEPT { return __storage_->__p2_; } + const path& path2() const noexcept { return __storage_->__p2_; } ~filesystem_error() override; // key function _LIBCPP_INLINE_VISIBILITY - const char* what() const _NOEXCEPT override { + const char* what() const noexcept override { return __storage_->__what_.c_str(); } @@ -1424,7 +1426,7 @@ void current_path(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -void current_path(const path& __p, error_code& __ec) _NOEXCEPT { +void current_path(const path& __p, error_code& __ec) noexcept { __current_path(__p, &__ec); } @@ -1496,7 +1498,7 @@ void copy_symlink(const path& __existing, const path& __new) { } inline _LIBCPP_INLINE_VISIBILITY -void copy_symlink(const path& __ext, const path& __new, error_code& __ec) _NOEXCEPT { +void copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept { __copy_symlink(__ext, __new, &__ec); } @@ -1516,7 +1518,7 @@ bool create_directory(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool create_directory(const path& __p, error_code& __ec) _NOEXCEPT { +bool create_directory(const path& __p, error_code& __ec) noexcept { return __create_directory(__p, &__ec); } @@ -1526,7 +1528,7 @@ bool create_directory(const path& __p, const path& __attrs) { } inline _LIBCPP_INLINE_VISIBILITY -bool create_directory(const path& __p, const path& __attrs, error_code& __ec) _NOEXCEPT { +bool create_directory(const path& __p, const path& __attrs, error_code& __ec) noexcept { return __create_directory(__p, __attrs, &__ec); } @@ -1537,7 +1539,7 @@ void create_directory_symlink(const path& __to, const path& __new) { inline _LIBCPP_INLINE_VISIBILITY void create_directory_symlink(const path& __to, const path& __new, - error_code& __ec) _NOEXCEPT { + error_code& __ec) noexcept { __create_directory_symlink(__to, __new, &__ec); } @@ -1547,7 +1549,7 @@ void create_hard_link(const path& __to, const path& __new) { } inline _LIBCPP_INLINE_VISIBILITY -void create_hard_link(const path& __to, const path& __new, error_code& __ec) _NOEXCEPT { +void create_hard_link(const path& __to, const path& __new, error_code& __ec) noexcept { __create_hard_link(__to, __new, &__ec); } @@ -1558,17 +1560,17 @@ void create_symlink(const path& __to, const path& __new) { inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to, const path& __new, - error_code& __ec) _NOEXCEPT { + error_code& __ec) noexcept { return __create_symlink(__to, __new, &__ec); } inline _LIBCPP_INLINE_VISIBILITY -bool status_known(file_status __s) _NOEXCEPT { +bool status_known(file_status __s) noexcept { return __s.type() != file_type::none; } inline _LIBCPP_INLINE_VISIBILITY -bool exists(file_status __s) _NOEXCEPT { +bool exists(file_status __s) noexcept { return status_known(__s) && __s.type() != file_type::not_found; } @@ -1578,7 +1580,7 @@ bool exists(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool exists(const path& __p, error_code& __ec) _NOEXCEPT { +bool exists(const path& __p, error_code& __ec) noexcept { auto __s = __status(__p, &__ec); if (status_known(__s)) __ec.clear(); return exists(__s); @@ -1590,7 +1592,7 @@ bool equivalent(const path& __p1, const path& __p2) { } inline _LIBCPP_INLINE_VISIBILITY -bool equivalent(const path& __p1, const path& __p2, error_code& __ec) _NOEXCEPT { +bool equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept { return __equivalent(__p1, __p2, &__ec); } @@ -1600,7 +1602,7 @@ uintmax_t file_size(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -uintmax_t file_size(const path& __p, error_code& __ec) _NOEXCEPT { +uintmax_t file_size(const path& __p, error_code& __ec) noexcept { return __file_size(__p, &__ec); } @@ -1610,12 +1612,12 @@ uintmax_t hard_link_count(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -uintmax_t hard_link_count(const path& __p, error_code& __ec) _NOEXCEPT { +uintmax_t hard_link_count(const path& __p, error_code& __ec) noexcept { return __hard_link_count(__p, &__ec); } inline _LIBCPP_INLINE_VISIBILITY -bool is_block_file(file_status __s) _NOEXCEPT { +bool is_block_file(file_status __s) noexcept { return __s.type() == file_type::block; } @@ -1625,12 +1627,12 @@ bool is_block_file(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool is_block_file(const path& __p, error_code& __ec) _NOEXCEPT { +bool is_block_file(const path& __p, error_code& __ec) noexcept { return is_block_file(__status(__p, &__ec)); } inline _LIBCPP_INLINE_VISIBILITY -bool is_character_file(file_status __s) _NOEXCEPT { +bool is_character_file(file_status __s) noexcept { return __s.type() == file_type::character; } @@ -1640,12 +1642,12 @@ bool is_character_file(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool is_character_file(const path& __p, error_code& __ec) _NOEXCEPT { +bool is_character_file(const path& __p, error_code& __ec) noexcept { return is_character_file(__status(__p, &__ec)); } inline _LIBCPP_INLINE_VISIBILITY -bool is_directory(file_status __s) _NOEXCEPT { +bool is_directory(file_status __s) noexcept { return __s.type() == file_type::directory; } @@ -1655,7 +1657,7 @@ bool is_directory(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool is_directory(const path& __p, error_code& __ec) _NOEXCEPT { +bool is_directory(const path& __p, error_code& __ec) noexcept { return is_directory(__status(__p, &__ec)); } @@ -1670,7 +1672,7 @@ bool is_empty(const path& __p, error_code& __ec) { } inline _LIBCPP_INLINE_VISIBILITY -bool is_fifo(file_status __s) _NOEXCEPT { +bool is_fifo(file_status __s) noexcept { return __s.type() == file_type::fifo; } inline _LIBCPP_INLINE_VISIBILITY @@ -1679,12 +1681,12 @@ bool is_fifo(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool is_fifo(const path& __p, error_code& __ec) _NOEXCEPT { +bool is_fifo(const path& __p, error_code& __ec) noexcept { return is_fifo(__status(__p, &__ec)); } inline _LIBCPP_INLINE_VISIBILITY -bool is_regular_file(file_status __s) _NOEXCEPT { +bool is_regular_file(file_status __s) noexcept { return __s.type() == file_type::regular; } @@ -1694,12 +1696,12 @@ bool is_regular_file(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool is_regular_file(const path& __p, error_code& __ec) _NOEXCEPT { +bool is_regular_file(const path& __p, error_code& __ec) noexcept { return is_regular_file(__status(__p, &__ec)); } inline _LIBCPP_INLINE_VISIBILITY -bool is_socket(file_status __s) _NOEXCEPT { +bool is_socket(file_status __s) noexcept { return __s.type() == file_type::socket; } @@ -1709,12 +1711,12 @@ bool is_socket(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool is_socket(const path& __p, error_code& __ec) _NOEXCEPT { +bool is_socket(const path& __p, error_code& __ec) noexcept { return is_socket(__status(__p, &__ec)); } inline _LIBCPP_INLINE_VISIBILITY -bool is_symlink(file_status __s) _NOEXCEPT { +bool is_symlink(file_status __s) noexcept { return __s.type() == file_type::symlink; } @@ -1724,12 +1726,12 @@ bool is_symlink(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool is_symlink(const path& __p, error_code& __ec) _NOEXCEPT { +bool is_symlink(const path& __p, error_code& __ec) noexcept { return is_symlink(__symlink_status(__p, &__ec)); } inline _LIBCPP_INLINE_VISIBILITY -bool is_other(file_status __s) _NOEXCEPT { +bool is_other(file_status __s) noexcept { return exists(__s) && !is_regular_file(__s) && !is_directory(__s) && !is_symlink(__s); } @@ -1740,7 +1742,7 @@ bool is_other(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool is_other(const path& __p, error_code& __ec) _NOEXCEPT { +bool is_other(const path& __p, error_code& __ec) noexcept { return is_other(__status(__p, &__ec)); } @@ -1750,7 +1752,7 @@ file_time_type last_write_time(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -file_time_type last_write_time(const path& __p, error_code& __ec) _NOEXCEPT { +file_time_type last_write_time(const path& __p, error_code& __ec) noexcept { return __last_write_time(__p, &__ec); } @@ -1760,7 +1762,7 @@ void last_write_time(const path& __p, file_time_type __t) { } inline _LIBCPP_INLINE_VISIBILITY -void last_write_time(const path& __p, file_time_type __t, error_code& __ec) _NOEXCEPT { +void last_write_time(const path& __p, file_time_type __t, error_code& __ec) noexcept { __last_write_time(__p, __t, &__ec); } @@ -1771,7 +1773,7 @@ void permissions(const path& __p, perms __prms, } inline _LIBCPP_INLINE_VISIBILITY -void permissions(const path& __p, perms __prms, error_code& __ec) _NOEXCEPT { +void permissions(const path& __p, perms __prms, error_code& __ec) noexcept { __permissions(__p, __prms, perm_options::replace, &__ec); } @@ -1841,7 +1843,7 @@ bool remove(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -bool remove(const path& __p, error_code& __ec) _NOEXCEPT { +bool remove(const path& __p, error_code& __ec) noexcept { return __remove(__p, &__ec); } @@ -1861,7 +1863,7 @@ void rename(const path& __from, const path& __to) { } inline _LIBCPP_INLINE_VISIBILITY -void rename(const path& __from, const path& __to, error_code& __ec) _NOEXCEPT { +void rename(const path& __from, const path& __to, error_code& __ec) noexcept { return __rename(__from, __to, &__ec); } @@ -1871,7 +1873,7 @@ void resize_file(const path& __p, uintmax_t __ns) { } inline _LIBCPP_INLINE_VISIBILITY -void resize_file(const path& __p, uintmax_t __ns, error_code& __ec) _NOEXCEPT { +void resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept { return __resize_file(__p, __ns, &__ec); } @@ -1881,7 +1883,7 @@ space_info space(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -space_info space(const path& __p, error_code& __ec) _NOEXCEPT { +space_info space(const path& __p, error_code& __ec) noexcept { return __space(__p, &__ec); } @@ -1891,7 +1893,7 @@ file_status status(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -file_status status(const path& __p, error_code& __ec) _NOEXCEPT { +file_status status(const path& __p, error_code& __ec) noexcept { return __status(__p, &__ec); } @@ -1901,7 +1903,7 @@ file_status symlink_status(const path& __p) { } inline _LIBCPP_INLINE_VISIBILITY -file_status symlink_status(const path& __p, error_code& __ec) _NOEXCEPT { +file_status symlink_status(const path& __p, error_code& __ec) noexcept { return __symlink_status(__p, &__ec); } @@ -1936,9 +1938,9 @@ class directory_entry public: // constructors and destructors - directory_entry() _NOEXCEPT = default; + directory_entry() noexcept = default; directory_entry(directory_entry const&) = default; - directory_entry(directory_entry&&) _NOEXCEPT = default; + directory_entry(directory_entry&&) noexcept = default; _LIBCPP_INLINE_VISIBILITY explicit directory_entry(_Path const& __p) : __p_(__p) { @@ -1954,7 +1956,7 @@ public: ~directory_entry() {} directory_entry& operator=(directory_entry const&) = default; - directory_entry& operator=(directory_entry&&) _NOEXCEPT = default; + directory_entry& operator=(directory_entry&&) noexcept = default; _LIBCPP_INLINE_VISIBILITY void assign(_Path const& __p) { @@ -1988,15 +1990,15 @@ public: } _LIBCPP_INLINE_VISIBILITY - void refresh(error_code& __ec) _NOEXCEPT { __refresh(&__ec); } + void refresh(error_code& __ec) noexcept { __refresh(&__ec); } _LIBCPP_INLINE_VISIBILITY - _Path const& path() const _NOEXCEPT { + _Path const& path() const noexcept { return __p_; } _LIBCPP_INLINE_VISIBILITY - operator const _Path&() const _NOEXCEPT { + operator const _Path&() const noexcept { return __p_; } @@ -2125,7 +2127,7 @@ public: } _LIBCPP_INLINE_VISIBILITY - file_status status(error_code& __ec) const _NOEXCEPT { + file_status status(error_code& __ec) const noexcept { return __get_status(&__ec); } @@ -2135,37 +2137,37 @@ public: } _LIBCPP_INLINE_VISIBILITY - file_status symlink_status(error_code& __ec) const _NOEXCEPT { + file_status symlink_status(error_code& __ec) const noexcept { return __get_symlink_status(&__ec); } _LIBCPP_INLINE_VISIBILITY - bool operator< (directory_entry const& __rhs) const _NOEXCEPT { + bool operator< (directory_entry const& __rhs) const noexcept { return __p_ < __rhs.__p_; } _LIBCPP_INLINE_VISIBILITY - bool operator==(directory_entry const& __rhs) const _NOEXCEPT { + bool operator==(directory_entry const& __rhs) const noexcept { return __p_ == __rhs.__p_; } _LIBCPP_INLINE_VISIBILITY - bool operator!=(directory_entry const& __rhs) const _NOEXCEPT { + bool operator!=(directory_entry const& __rhs) const noexcept { return __p_ != __rhs.__p_; } _LIBCPP_INLINE_VISIBILITY - bool operator<=(directory_entry const& __rhs) const _NOEXCEPT { + bool operator<=(directory_entry const& __rhs) const noexcept { return __p_ <= __rhs.__p_; } _LIBCPP_INLINE_VISIBILITY - bool operator> (directory_entry const& __rhs) const _NOEXCEPT { + bool operator> (directory_entry const& __rhs) const noexcept { return __p_ > __rhs.__p_; } _LIBCPP_INLINE_VISIBILITY - bool operator>=(directory_entry const& __rhs) const _NOEXCEPT { + bool operator>=(directory_entry const& __rhs) const noexcept { return __p_ >= __rhs.__p_; } @@ -2434,7 +2436,7 @@ public: public: //ctor & dtor - directory_iterator() _NOEXCEPT + directory_iterator() noexcept { } explicit directory_iterator(const path& __p) @@ -2458,7 +2460,7 @@ public: directory_iterator(directory_iterator&&) = default; directory_iterator& operator=(const directory_iterator&) = default; - directory_iterator& operator=(directory_iterator&& __o) _NOEXCEPT { + directory_iterator& operator=(directory_iterator&& __o) noexcept { // non-default implementation provided to support self-move assign. if (this != &__o) { __imp_ = _VSTD::move(__o.__imp_); @@ -2491,7 +2493,7 @@ public: private: inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const directory_iterator& __lhs, - const directory_iterator& __rhs) _NOEXCEPT; + const directory_iterator& __rhs) noexcept; // construct the dir_stream _LIBCPP_FUNC_VIS @@ -2511,24 +2513,24 @@ private: inline _LIBCPP_INLINE_VISIBILITY bool operator==(const directory_iterator& __lhs, - const directory_iterator& __rhs) _NOEXCEPT { + const directory_iterator& __rhs) noexcept { return __lhs.__imp_ == __rhs.__imp_; } inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const directory_iterator& __lhs, - const directory_iterator& __rhs) _NOEXCEPT { + const directory_iterator& __rhs) noexcept { return !(__lhs == __rhs); } // enable directory_iterator range-based for statements inline _LIBCPP_INLINE_VISIBILITY -directory_iterator begin(directory_iterator __iter) _NOEXCEPT { +directory_iterator begin(directory_iterator __iter) noexcept { return __iter; } inline _LIBCPP_INLINE_VISIBILITY -directory_iterator end(const directory_iterator&) _NOEXCEPT { +directory_iterator end(const directory_iterator&) noexcept { return directory_iterator(); } @@ -2543,7 +2545,7 @@ public: public: // constructors and destructor _LIBCPP_INLINE_VISIBILITY - recursive_directory_iterator() _NOEXCEPT + recursive_directory_iterator() noexcept : __rec_(false) {} @@ -2644,7 +2646,7 @@ private: inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const recursive_directory_iterator&, - const recursive_directory_iterator&) _NOEXCEPT; + const recursive_directory_iterator&) noexcept; struct __shared_imp; shared_ptr<__shared_imp> __imp_; @@ -2654,30 +2656,32 @@ private: inline _LIBCPP_INLINE_VISIBILITY bool operator==(const recursive_directory_iterator& __lhs, - const recursive_directory_iterator& __rhs) _NOEXCEPT + const recursive_directory_iterator& __rhs) noexcept { return __lhs.__imp_ == __rhs.__imp_; } _LIBCPP_INLINE_VISIBILITY inline bool operator!=(const recursive_directory_iterator& __lhs, - const recursive_directory_iterator& __rhs) _NOEXCEPT + const recursive_directory_iterator& __rhs) noexcept { return !(__lhs == __rhs); } // enable recursive_directory_iterator range-based for statements inline _LIBCPP_INLINE_VISIBILITY -recursive_directory_iterator begin(recursive_directory_iterator __iter) _NOEXCEPT { +recursive_directory_iterator begin(recursive_directory_iterator __iter) noexcept { return __iter; } inline _LIBCPP_INLINE_VISIBILITY -recursive_directory_iterator end(const recursive_directory_iterator&) _NOEXCEPT { +recursive_directory_iterator end(const recursive_directory_iterator&) noexcept { return recursive_directory_iterator(); } _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM +#endif // !_LIBCPP_CXX03_LANG + _LIBCPP_POP_MACROS #endif // _LIBCPP_EXPERIMENTAL_FILESYSTEM diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index 22ad9c313..104d0aa7b 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -414,6 +414,4 @@ bool SetTimeStructTo(TimeStruct& TS, file_time_type NewTime) { _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM - - #endif // FILESYSTEM_COMMON_H diff --git a/test/std/experimental/filesystem/fs.req.macros/feature_macro.pass.cpp b/test/std/experimental/filesystem/fs.req.macros/feature_macro.pass.cpp index 42dfe9480..c82d558c1 100644 --- a/test/std/experimental/filesystem/fs.req.macros/feature_macro.pass.cpp +++ b/test/std/experimental/filesystem/fs.req.macros/feature_macro.pass.cpp @@ -7,18 +7,23 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 - // // #define __cpp_lib_experimental_filesystem 201406L -#include "filesystem_include.hpp" +#include +#include "test_macros.h" +#if TEST_STD_VER >= 11 #ifndef __cpp_lib_experimental_filesystem #error Filesystem feature test macro is not defined (__cpp_lib_experimental_filesystem) #elif __cpp_lib_experimental_filesystem != 201406L #error Filesystem feature test macro has an incorrect value (__cpp_lib_experimental_filesystem) #endif +#else // TEST_STD_VER < 11 +#ifdef __cpp_lib_experimental_filesystem +#error Filesystem feature test macro should not be defined in c++03 +#endif +#endif int main() { } -- GitLab From d3e32d2c5335150c0f9e02e4da2653a0b7da8bf8 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Wed, 25 Jul 2018 04:21:21 +0000 Subject: [PATCH 074/495] New test support for comparisons. Reviewed as https://reviews.llvm.org/D49773 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337885 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/support/test_comparisons.h | 175 ++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 test/support/test_comparisons.h diff --git a/test/support/test_comparisons.h b/test/support/test_comparisons.h new file mode 100644 index 000000000..a3f8dd9f8 --- /dev/null +++ b/test/support/test_comparisons.h @@ -0,0 +1,175 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// A set of routines for testing the comparison operators of a type +// +// XXXX6 tests all six comparison operators +// XXXX2 tests only op== and op!= +// +// AssertComparisonsXAreNoexcept static_asserts that the operations are all noexcept. +// AssertComparisonsXReturnBool static_asserts that the operations return bool. +// AssertComparisonsXConvertibleToBool static_asserts that the operations return something convertible to bool. + + +#ifndef TEST_COMPARISONS_H +#define TEST_COMPARISONS_H + +#include +#include "test_macros.h" + +// Test all six comparison operations for sanity +template +TEST_CONSTEXPR_CXX14 bool testComparisons6(const T& t1, const T& t2, bool isEqual, bool isLess) +{ + if (isEqual) + { + if (!(t1 == t2)) return false; + if (!(t2 == t1)) return false; + if ( (t1 != t2)) return false; + if ( (t2 != t1)) return false; + if ( (t1 < t2)) return false; + if ( (t2 < t1)) return false; + if (!(t1 <= t2)) return false; + if (!(t2 <= t1)) return false; + if ( (t1 > t2)) return false; + if ( (t2 > t1)) return false; + if (!(t1 >= t2)) return false; + if (!(t2 >= t1)) return false; + } + else if (isLess) + { + if ( (t1 == t2)) return false; + if ( (t2 == t1)) return false; + if (!(t1 != t2)) return false; + if (!(t2 != t1)) return false; + if (!(t1 < t2)) return false; + if ( (t2 < t1)) return false; + if (!(t1 <= t2)) return false; + if ( (t2 <= t1)) return false; + if ( (t1 > t2)) return false; + if (!(t2 > t1)) return false; + if ( (t1 >= t2)) return false; + if (!(t2 >= t1)) return false; + } + else /* greater */ + { + if ( (t1 == t2)) return false; + if ( (t2 == t1)) return false; + if (!(t1 != t2)) return false; + if (!(t2 != t1)) return false; + if ( (t1 < t2)) return false; + if (!(t2 < t1)) return false; + if ( (t1 <= t2)) return false; + if (!(t2 <= t1)) return false; + if (!(t1 > t2)) return false; + if ( (t2 > t1)) return false; + if (!(t1 >= t2)) return false; + if ( (t2 >= t1)) return false; + } + + return true; +} + +// Easy call when you can init from something already comparable. +template +TEST_CONSTEXPR_CXX14 bool testComparisons6Values(Param val1, Param val2) +{ + const bool isEqual = val1 == val2; + const bool isLess = val1 < val2; + + return testComparisons6(T{val1}, T{val2}, isEqual, isLess); +} + +template +void AssertComparisons6AreNoexcept() +{ + ASSERT_NOEXCEPT(std::declval() == std::declval()); + ASSERT_NOEXCEPT(std::declval() != std::declval()); + ASSERT_NOEXCEPT(std::declval() < std::declval()); + ASSERT_NOEXCEPT(std::declval() <= std::declval()); + ASSERT_NOEXCEPT(std::declval() > std::declval()); + ASSERT_NOEXCEPT(std::declval() >= std::declval()); +} + +template +void AssertComparisons6ReturnBool() +{ + ASSERT_SAME_TYPE(decltype(std::declval() == std::declval()), bool); + ASSERT_SAME_TYPE(decltype(std::declval() != std::declval()), bool); + ASSERT_SAME_TYPE(decltype(std::declval() < std::declval()), bool); + ASSERT_SAME_TYPE(decltype(std::declval() <= std::declval()), bool); + ASSERT_SAME_TYPE(decltype(std::declval() > std::declval()), bool); + ASSERT_SAME_TYPE(decltype(std::declval() >= std::declval()), bool); +} + + +template +void AssertComparisons6ConvertibleToBool() +{ + static_assert((std::is_convertible() == std::declval()), bool>::value), ""); + static_assert((std::is_convertible() != std::declval()), bool>::value), ""); + static_assert((std::is_convertible() < std::declval()), bool>::value), ""); + static_assert((std::is_convertible() <= std::declval()), bool>::value), ""); + static_assert((std::is_convertible() > std::declval()), bool>::value), ""); + static_assert((std::is_convertible() >= std::declval()), bool>::value), ""); +} + +// Test all six comparison operations for sanity +template +TEST_CONSTEXPR_CXX14 bool testComparisons2(const T& t1, const T& t2, bool isEqual) +{ + if (isEqual) + { + if (!(t1 == t2)) return false; + if (!(t2 == t1)) return false; + if ( (t1 != t2)) return false; + if ( (t2 != t1)) return false; + } + else /* greater */ + { + if ( (t1 == t2)) return false; + if ( (t2 == t1)) return false; + if (!(t1 != t2)) return false; + if (!(t2 != t1)) return false; + } + + return true; +} + +// Easy call when you can init from something already comparable. +template +TEST_CONSTEXPR_CXX14 bool testComparisons2Values(Param val1, Param val2) +{ + const bool isEqual = val1 == val2; + + return testComparisons2(T{val1}, T{val2}, isEqual); +} + +template +void AssertComparisons2AreNoexcept() +{ + ASSERT_NOEXCEPT(std::declval() == std::declval()); + ASSERT_NOEXCEPT(std::declval() != std::declval()); +} + +template +void AssertComparisons2ReturnBool() +{ + ASSERT_SAME_TYPE(decltype(std::declval() == std::declval()), bool); + ASSERT_SAME_TYPE(decltype(std::declval() != std::declval()), bool); +} + + +template +void AssertComparisons2ConvertibleToBool() +{ + static_assert((std::is_convertible() == std::declval()), bool>::value), ""); + static_assert((std::is_convertible() != std::declval()), bool>::value), ""); +} + +#endif // TEST_COMPARISONS_H -- GitLab From bb00305f46be91557039e55e9a61b358e08c4c36 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 04:21:59 +0000 Subject: [PATCH 075/495] Fix missing includes in format_string.hpp helper git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337886 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/support/format_string.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/support/format_string.hpp b/test/support/format_string.hpp index 17e467c8c..44dc30f55 100644 --- a/test/support/format_string.hpp +++ b/test/support/format_string.hpp @@ -5,23 +5,24 @@ #include #include #include +#include namespace format_string_detail { inline std::string format_string_imp(const char* msg, ...) { // we might need a second shot at this, so pre-emptivly make a copy struct GuardVAList { - va_list& target; + va_list& xtarget; bool active; - GuardVAList(va_list& target) : target(target), active(true) {} + GuardVAList(va_list& val) : xtarget(val), active(true) {} void clear() { if (active) - va_end(target); + va_end(xtarget); active = false; } ~GuardVAList() { if (active) - va_end(target); + va_end(xtarget); } }; va_list args; -- GitLab From 8410c8170ae75364dfb2891cc9be89aa4ba8ea41 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 04:46:32 +0000 Subject: [PATCH 076/495] Fix bugs in create_directory implementation. Libc++ was incorrectly reporting an error when the target of create_directory already exists, but was not a directory. This behavior is not specified in the most recent standard, which says no error should be reported. Additionally, libc++ failed to report an error when the attribute directory path didn't exist or didn't name a directory. This has been fixed as well. Although it's not clear if we should call status or symlink_status on the attribute directory. This patch chooses to still call status. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337888 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/operations.cpp | 6 ++- .../create_directories.pass.cpp | 32 ++++++++++++++++ .../create_directory.pass.cpp | 4 +- .../create_directory_with_attributes.pass.cpp | 37 +++++++++++++++++-- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index 089e34b20..dd8b43477 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -830,7 +830,7 @@ bool __create_directory(const path& p, error_code *ec) if (::mkdir(p.c_str(), static_cast(perms::all)) == 0) return true; - if (errno != EEXIST || !is_directory(p)) + if (errno != EEXIST) err.report(capture_errno()); return false; } @@ -845,10 +845,12 @@ bool __create_directory(path const & p, path const & attributes, auto st = detail::posix_stat(attributes, attr_stat, &mec); if (!status_known(st)) return err.report(mec); + if (!is_directory(st)) + return err.report(errc::not_a_directory, "the specified attribute path is invalid"); if (::mkdir(p.c_str(), attr_stat.st_mode) == 0) return true; - if (errno != EEXIST || !is_directory(p)) + if (errno != EEXIST) err.report(capture_errno()); return false; } diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp index e7962941c..8afc6102e 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp @@ -66,4 +66,36 @@ TEST_CASE(create_directories_multi_level) TEST_CHECK(is_directory(dir)); } +TEST_CASE(create_directory_symlinks) { + scoped_test_env env; + const path root = env.create_dir("dir"); + const path sym_dest_dead = env.make_env_path("dead"); + const path dead_sym = env.create_symlink(sym_dest_dead, "dir/sym_dir"); + const path target = env.make_env_path("dir/sym_dir/foo"); + { + std::error_code ec = GetTestEC(); + TEST_CHECK(create_directories(target, ec) == false); + TEST_CHECK(ec); + TEST_CHECK(!exists(sym_dest_dead)); + TEST_CHECK(!exists(dead_sym)); + } +} + + +TEST_CASE(create_directory_through_symlinks) { + scoped_test_env env; + const path root = env.create_dir("dir"); + const path sym_dir = env.create_symlink(root, "sym_dir"); + const path target = env.make_env_path("sym_dir/foo"); + const path resolved_target = env.make_env_path("dir/foo"); + TEST_REQUIRE(is_directory(sym_dir)); + { + std::error_code ec = GetTestEC(); + TEST_CHECK(create_directories(target, ec) == true); + TEST_CHECK(!ec); + TEST_CHECK(is_directory(target)); + TEST_CHECK(is_directory(resolved_target)); + } +} + TEST_SUITE_END() diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp index 4bc30c2b3..7885c4a54 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp @@ -94,9 +94,9 @@ TEST_CASE(dest_is_file) { scoped_test_env env; const path file = env.create_file("file", 42); - std::error_code ec; + std::error_code ec = GetTestEC(); TEST_CHECK(fs::create_directory(file, ec) == false); - TEST_CHECK(ec); + TEST_CHECK(!ec); TEST_CHECK(is_regular_file(file)); } diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp index 8ec22f1f9..2ee55fc4c 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp @@ -82,9 +82,9 @@ TEST_CASE(create_directory_multi_level) const path dir = env.make_env_path("dir1/dir2"); const path dir1 = env.make_env_path("dir1"); const path attr_dir = env.create_dir("attr_dir"); - std::error_code ec; + std::error_code ec = GetTestEC(); TEST_CHECK(fs::create_directory(dir, attr_dir, ec) == false); - TEST_CHECK(ec); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); TEST_CHECK(!is_directory(dir)); TEST_CHECK(!is_directory(dir1)); } @@ -94,10 +94,39 @@ TEST_CASE(dest_is_file) scoped_test_env env; const path file = env.create_file("file", 42); const path attr_dir = env.create_dir("attr_dir"); - std::error_code ec; + std::error_code ec = GetTestEC(); TEST_CHECK(fs::create_directory(file, attr_dir, ec) == false); - TEST_CHECK(ec); + TEST_CHECK(!ec); TEST_CHECK(is_regular_file(file)); } +TEST_CASE(attr_dir_is_invalid) { + scoped_test_env env; + const path file = env.create_file("file", 42); + const path dest = env.make_env_path("dir"); + const path dne = env.make_env_path("dne"); + { + std::error_code ec = GetTestEC(); + TEST_CHECK(create_directory(dest, file, ec) == false); + TEST_CHECK(ErrorIs(ec, std::errc::not_a_directory)); + } + TEST_REQUIRE(!exists(dest)); + { + std::error_code ec = GetTestEC(); + TEST_CHECK(create_directory(dest, dne, ec) == false); + TEST_CHECK(ErrorIs(ec, std::errc::not_a_directory)); + } +} + +TEST_CASE(dest_is_symlink) { + scoped_test_env env; + const path dir = env.create_dir("dir"); + const path sym = env.create_symlink("dne_sym", "dne_sym_name"); + { + std::error_code ec = GetTestEC(); + TEST_CHECK(create_directory(sym, dir, ec) == false); + TEST_CHECK(!ec); + } +} + TEST_SUITE_END() -- GitLab From f562b9b331b622ab75c971c33aae5018e814d417 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 10:17:04 +0000 Subject: [PATCH 077/495] Fix typos, spelling, and grammar in the FileTimeType design docs. I'm sure I'll discover more mistakes as I go on... git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337897 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/DesignDocs/FileTimeType.rst | 73 ++++++++++++++++---------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/docs/DesignDocs/FileTimeType.rst b/docs/DesignDocs/FileTimeType.rst index 83d5fed16..ed62a0a6c 100644 --- a/docs/DesignDocs/FileTimeType.rst +++ b/docs/DesignDocs/FileTimeType.rst @@ -83,14 +83,14 @@ To get the same range, we would need to drop our resolution to that of seconds to come close to having the same range. This begs the question, is the range problem "really a problem"? Sane usages -of file time stamps shouldn't exceed +/- 300, so should we care to support it? +of file time stamps shouldn't exceed +/- 300 years, so should we care to support it? I believe the answer is yes. We're not designing the filesystem time API, we're providing glorified C++ wrappers for it. If the underlying API supports a value, then we should too. Our wrappers should not place artificial restrictions on users that are not present in the underlying filesystem. -Additionally, having a smaller range that the underlying filesystem forces the +Having a smaller range that the underlying filesystem forces the implementation to report ``value_too_large`` errors when it encounters a time point that it can't represent. This can cause the call to ``last_write_time`` to throw in cases where the user was confident the call should succeed. (See below) @@ -135,7 +135,7 @@ Having a Smaller Resolution than ``timespec`` --------------------------------------------- As mentioned in the previous section, one way to solve the range problem -is by reducing the resolution, and matching the range of ``timespec`` using a +is by reducing the resolution. But matching the range of ``timespec`` using a 64 bit representation requires limiting the resolution to seconds. So we might ask: Do users "need" nanosecond precision? Is seconds not good enough? @@ -148,16 +148,16 @@ representation, not design it. Having a Larger Range than ``timespec`` ---------------------------------------- -We also should consider the opposite problem of having ``file_time_type`` -be able to represent a larger range than that of ``timespec``. At least in +We should also consider the opposite problem of having a ``file_time_type`` +that is able to represent a larger range than ``timespec``. At least in this case ``last_write_time`` can be used to get and set all possible values supported by the underlying filesystem; meaning ``last_write_time(p)`` will -never throw a overflow error. +never throw a overflow error when retrieving a value. -However, this introduces a new problem, where users are allowed to create time -points beyond what the filesystem can represent. Two particular values are -``file_time_type::min()`` and ``file_time_type::max()``. As such the following -code would throw: +However, this introduces a new problem, where users are allowed to attempt to +create a time point beyond what the filesystem can represent. Two particular +values which cause this are ``file_time_type::min()`` and +``file_time_type::max()``. As a result, the following code would throw: .. code-block:: cpp @@ -167,8 +167,8 @@ code would throw: } Apart from cases explicitly using ``min`` and ``max``, I don't see users taking -a valid time point, adding a couple hundred billions of years to it in error, -and then trying to update a files write time with that value very often. +a valid time point, adding a couple hundred billions of years in error, +and then trying to update a file's write time to that value very often. Compared to having a smaller range, this problem seems preferable. At least now we can represent any time point the filesystem can, so users won't be forced @@ -190,10 +190,10 @@ than 64 bits. The possible solutions include using ``__int128_t``, emulating a arithmetic type. All three will solve allow us to, at minimum, match the range and resolution, and the last one might even allow us to match them exactly. -But when considering these potential solutions, we need to consider more than -just the values they can represent. We need to consider the effect they will have -on users and their code. For example, each of them breaks the following code -in some way: +But when considering these potential solutions we need to consider more than +just the values they can represent. We need to consider the effects they will +have on users and their code. For example, each of them breaks the following +code in some way: .. code-block:: cpp @@ -234,12 +234,12 @@ in some way: Each of the above examples would require a user to adjust their filesystem code -to the particular eccentricities of the representation type, hopefully in -such a way that the code is still portable across implementations. +to the particular eccentricities of the representation, hopefully only in such +a way that the code is still portable across implementations. -It seems like at least some of the above issues are unavoidable, no matter -what representation we choose. But some representations may be quirkier than -others, and, as I'll argue later, using an actual arithmetic type (``__int128_t``) +At least some of the above issues are unavoidable, no matter what +representation we choose. But some representations may be quirkier than others, +and, as I'll argue later, using an actual arithmetic type (``__int128_t``) provides the least aberrant behavior. @@ -270,19 +270,19 @@ look like. // ... arithmetic operators ... // The first thing to notice is that we can't construct ``fs_timespec_rep`` like -a ``timespec`` by passing ``{secs, nsecs}``. Instead we're limited to constructing -it from a single 64 bit integer. +a ``timespec`` by passing ``{secs, nsecs}``. Instead we're limited to +constructing it from a single 64 bit integer. We also can't allow the user to inspect the ``tv_sec`` or ``tv_nsec`` values directly. A ``chrono::duration`` represents its value as a tick period and a number of ticks stored using ``rep``. The representation is unaware of the -tick period its being used to represent, but ``timespec`` is setup to assume a -nanosecond tick period. That's the only case where the names of the ``tv_sec`` -and ``tv_nsec`` members matches the values they store. +tick period it is being used to represent, but ``timespec`` is setup to assume +a nanosecond tick period; which is the only case where the names ``tv_sec`` +and ``tv_nsec`` matche the values they store. -When we convert a nanosecond duration to a seconds, ``fs_timespec_rep`` -will be using ``tv_sec`` to represent the number of giga seconds, and ``tv_nsec`` -the remaining seconds. Lets consider how this might cause a bug were users allowed +When we convert a nanosecond duration to a seconds, ``fs_timespec_rep`` will +use ``tv_sec`` to represent the number of giga seconds, and ``tv_nsec`` the +remaining seconds. Lets consider how this might cause a bug were users allowed to manipulate the fields directly. .. code-block:: cpp @@ -309,7 +309,7 @@ to manipulate the fields directly. return secs.count().tv_sec; // Oops! } -However, despite ``fs_timespec_rep`` not being usable in any manner resembling +Despite ``fs_timespec_rep`` not being usable in any manner resembling ``timespec``, it still might buy us our goal of matching its range exactly, right? @@ -330,10 +330,11 @@ and maximum values for a custom representation. It looks like this: } }; -Notice that ``duration_values`` doesn't tell the representation what tick period -it's actually representing. This would indeed correctly limit the range of -``duration`` to exactly that of ``timespec``. But -nanoseconds isn't the only tick period it will be used to represent. For example: +Notice that ``duration_values`` doesn't tell the representation what tick +period it's actually representing. This would indeed correctly limit the range +of ``duration`` to exactly that of ``timespec``. But +nanoseconds isn't the only tick period it will be used to represent. For +example: .. code-block:: cpp @@ -344,7 +345,7 @@ nanoseconds isn't the only tick period it will be used to represent. For example fs_nsec nsecs(fs_seconds::max()); // Truncates } -Though the above example may appear silly, I it follows from the incorrect +Though the above example may appear silly, I think it follows from the incorrect notion that using a ``timespec`` rep in chrono actually makes it act as if it were an actual ``timespec``. @@ -411,7 +412,7 @@ __int128_t Pros: * It is an integer type. -* It makes the implementation simply and efficient. +* It makes the implementation simple and efficient. * Acts exactly like other arithmetic types. * Can be implicitly converted to a builtin integer type by the user. -- GitLab From ed7123bdc2ca928b4875d155d3783489ad8d5576 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 10:22:07 +0000 Subject: [PATCH 078/495] Fix another typo in the FileTimeType docs git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337900 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/DesignDocs/FileTimeType.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DesignDocs/FileTimeType.rst b/docs/DesignDocs/FileTimeType.rst index ed62a0a6c..4686e0aef 100644 --- a/docs/DesignDocs/FileTimeType.rst +++ b/docs/DesignDocs/FileTimeType.rst @@ -224,7 +224,7 @@ code in some way: // Implicit truncation during conversion bug. intmax_t get_time_in_seconds(path p) { - using fs_seconds = duration; + using fs_seconds = duration >; auto tp = last_write_time(p); // This works with truncation for __int128_t, but what does it do for -- GitLab From e428b57e79fa2b159c92d6abb4797b6faf1f2f6e Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 11:16:39 +0000 Subject: [PATCH 079/495] Fix diagnostic test to tolerate Clang diagnosing it as well. Tuple has tests that ensure we diagnose non-lifetime extended reference bindings inside tuples constructors. As of yesterday, Clang now does this for us. Adjust the test to tolerate the new diagnostics, while still testing that we emit diagnostics of our own. Maybe after this version of Clang has been adopted by most users we should remove our diagnostics; but for now more error detection is better! git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337905 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../PR20855_tuple_ref_binding_diagnostics.fail.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.fail.cpp b/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.fail.cpp index 3300f7e83..cc222a70e 100644 --- a/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.fail.cpp +++ b/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.fail.cpp @@ -46,7 +46,12 @@ void F(typename CannotDeduce>::type const&) {} int main() { #if TEST_HAS_BUILTIN_IDENTIFIER(__reference_binds_to_temporary) + // Test that we emit our diagnostic from the library. // expected-error@tuple:* 8 {{"Attempted construction of reference element binds to a temporary whose lifetime has ended"}} + + // Good news everybody! Clang now diagnoses this for us! + // expected-error@tuple:* 0+ {{reference member '__value_' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} + { F(std::make_tuple(1, "abc")); // expected-note 1 {{requested here}} } -- GitLab From d9cfbf1a891cbc09edf0f618d945efe215eca01e Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 25 Jul 2018 13:40:49 +0000 Subject: [PATCH 080/495] [NFC] Fix grammatical mistakes in libc++ FileTimeType design docs git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337925 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/DesignDocs/FileTimeType.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/DesignDocs/FileTimeType.rst b/docs/DesignDocs/FileTimeType.rst index 4686e0aef..488ff174b 100644 --- a/docs/DesignDocs/FileTimeType.rst +++ b/docs/DesignDocs/FileTimeType.rst @@ -61,7 +61,7 @@ of representing the range of the ``timespec`` struct? Problems To Consider ==================== -Before considering solutions, lets consider the problems they should solve, +Before considering solutions, let's consider the problems they should solve, and how important solving those problems are: @@ -187,7 +187,7 @@ Source Code Portability Across Implementations As we've discussed, ``file_time_type`` needs a representation that uses more than 64 bits. The possible solutions include using ``__int128_t``, emulating a 128 bit integer using a class, or potentially defining a ``timespec`` like -arithmetic type. All three will solve allow us to, at minimum, match the range +arithmetic type. All three will allow us to, at minimum, match the range and resolution, and the last one might even allow us to match them exactly. But when considering these potential solutions we need to consider more than @@ -214,7 +214,7 @@ code in some way: file_time_type correct_timespec_to_file_time_type(struct timespec ts) { // This is the correct version of the above example, where we - // avoid using the chrono typedefs as their not sufficient. + // avoid using the chrono typedefs as they're not sufficient. // Can we expect users to avoid this bug? using fs_seconds = chrono::duration; using fs_nanoseconds = chrono::duration; @@ -252,7 +252,7 @@ what the underlying system uses, and because it might allow us to match the range and resolution exactly. But would it work with chrono? And could it still act at all like a ``timespec`` struct? -For ease of consideration, lets consider the what the implementation might +For ease of consideration, let's consider what the implementation might look like. .. code-block:: cpp @@ -278,11 +278,11 @@ directly. A ``chrono::duration`` represents its value as a tick period and a number of ticks stored using ``rep``. The representation is unaware of the tick period it is being used to represent, but ``timespec`` is setup to assume a nanosecond tick period; which is the only case where the names ``tv_sec`` -and ``tv_nsec`` matche the values they store. +and ``tv_nsec`` match the values they store. -When we convert a nanosecond duration to a seconds, ``fs_timespec_rep`` will +When we convert a nanosecond duration to seconds, ``fs_timespec_rep`` will use ``tv_sec`` to represent the number of giga seconds, and ``tv_nsec`` the -remaining seconds. Lets consider how this might cause a bug were users allowed +remaining seconds. Let's consider how this might cause a bug were users allowed to manipulate the fields directly. .. code-block:: cpp @@ -364,8 +364,8 @@ described by this paper. Obviously our implementation for 32-bit builds should act as similarly to the 64-bit build as possible. Code which compiles in one, should compile in the other. This consideration is important when choosing between ``__int128_t`` and -emulating ``timespec``. The solution which provides the most uniformity is -the preferable one, with the least eccentricity is the preferable one. +emulating ``timespec``. The solution which provides the most uniformity with +the least eccentricity is the preferable one. Summary ======= @@ -391,7 +391,7 @@ The Potential Solutions Pros: -* As a type ``long long`` places the nicest with others: +* As a type ``long long`` plays the nicest with others: * It works with streaming operators and other library entities which support builtin integer types, but don't support ``__int128_t``. -- GitLab From b52e084ca81da9f2d03ab21a8625aeada7e64a67 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Wed, 25 Jul 2018 18:24:23 +0000 Subject: [PATCH 081/495] [windows] Fix warning about comparing ints of different signs This fixes a warning like this: warning: comparison of integers of different signs: 'std::__1::__libcpp_tls_key' (aka 'long') and 'DWORD' (aka 'unsigned long') [-Wsign-compare] if (*__key == FLS_OUT_OF_INDEXES) ~~~~~~ ^ ~~~~~~~~~~~~~~~~~~ Differential Revision: https://reviews.llvm.org/D49782 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337946 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/support/win32/thread_win32.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/support/win32/thread_win32.cpp b/src/support/win32/thread_win32.cpp index 471049429..1567042d8 100644 --- a/src/support/win32/thread_win32.cpp +++ b/src/support/win32/thread_win32.cpp @@ -254,9 +254,10 @@ void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) int __libcpp_tls_create(__libcpp_tls_key* __key, void(_LIBCPP_TLS_DESTRUCTOR_CC* __at_exit)(void*)) { - *__key = FlsAlloc(__at_exit); - if (*__key == FLS_OUT_OF_INDEXES) + DWORD index = FlsAlloc(__at_exit); + if (index == FLS_OUT_OF_INDEXES) return GetLastError(); + *__key = index; return 0; } -- GitLab From a1ae56c033b41d4eaffb3769f669eadb992ae2e1 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 25 Jul 2018 19:40:01 +0000 Subject: [PATCH 082/495] [libc++] Factor duplicate code into function templates Summary: The exact same code was replicated 11 times for implementing the basic_istream input operators (those that don't use numeric_limits). The same code was also duplicated twice for implementing the basic_istream input operators that take numeric_limits into account. This commit factors the common code into function templates to avoid the duplication. Reviewers: mclow.lists, EricWF Subscribers: christof, dexonsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D49808 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337955 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/istream | 319 ++++++++---------------------------------------- 1 file changed, 50 insertions(+), 269 deletions(-) diff --git a/include/istream b/include/istream index f2579c14d..71c162b0d 100644 --- a/include/istream +++ b/include/istream @@ -358,381 +358,162 @@ basic_istream<_CharT, _Traits>::~basic_istream() { } -template +template +_LIBCPP_INLINE_VISIBILITY basic_istream<_CharT, _Traits>& -basic_istream<_CharT, _Traits>::operator>>(unsigned short& __n) -{ +__input_arithmetic(basic_istream<_CharT, _Traits>& __is, _Tp& __n) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); + typename basic_istream<_CharT, _Traits>::sentry __s(__is); if (__s) { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; + typedef istreambuf_iterator<_CharT, _Traits> _Ip; + typedef num_get<_CharT, _Ip> _Fp; ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); + use_facet<_Fp>(__is.getloc()).get(_Ip(__is), _Ip(), __is, __err, __n); + __is.setstate(__err); } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - this->__set_badbit_and_consider_rethrow(); + __is.__set_badbit_and_consider_rethrow(); } #endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return __is; +} + +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::operator>>(unsigned short& __n) +{ + return _VSTD::__input_arithmetic(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(unsigned int& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(long& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(unsigned long& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(long long& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(unsigned long long& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(float& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(double& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(long double& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(bool& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(void*& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __n); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic(*this, __n); } -template +template +_LIBCPP_INLINE_VISIBILITY basic_istream<_CharT, _Traits>& -basic_istream<_CharT, _Traits>::operator>>(short& __n) -{ +__input_arithmetic_with_numeric_limits(basic_istream<_CharT, _Traits>& __is, _Tp& __n) { #ifndef _LIBCPP_NO_EXCEPTIONS try { #endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); + typename basic_istream<_CharT, _Traits>::sentry __s(__is); if (__s) { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; + typedef istreambuf_iterator<_CharT, _Traits> _Ip; + typedef num_get<_CharT, _Ip> _Fp; ios_base::iostate __err = ios_base::goodbit; long __temp; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __temp); - if (__temp < numeric_limits::min()) + use_facet<_Fp>(__is.getloc()).get(_Ip(__is), _Ip(), __is, __err, __temp); + if (__temp < numeric_limits<_Tp>::min()) { __err |= ios_base::failbit; - __n = numeric_limits::min(); + __n = numeric_limits<_Tp>::min(); } - else if (__temp > numeric_limits::max()) + else if (__temp > numeric_limits<_Tp>::max()) { __err |= ios_base::failbit; - __n = numeric_limits::max(); + __n = numeric_limits<_Tp>::max(); } else - __n = static_cast(__temp); - this->setstate(__err); + __n = static_cast<_Tp>(__temp); + __is.setstate(__err); } #ifndef _LIBCPP_NO_EXCEPTIONS } catch (...) { - this->__set_badbit_and_consider_rethrow(); + __is.__set_badbit_and_consider_rethrow(); } #endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return __is; +} + +template +basic_istream<_CharT, _Traits>& +basic_istream<_CharT, _Traits>::operator>>(short& __n) +{ + return _VSTD::__input_arithmetic_with_numeric_limits(*this, __n); } template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>::operator>>(int& __n) { -#ifndef _LIBCPP_NO_EXCEPTIONS - try - { -#endif // _LIBCPP_NO_EXCEPTIONS - sentry __s(*this); - if (__s) - { - typedef istreambuf_iterator _Ip; - typedef num_get _Fp; - ios_base::iostate __err = ios_base::goodbit; - long __temp; - use_facet<_Fp>(this->getloc()).get(_Ip(*this), _Ip(), *this, __err, __temp); - if (__temp < numeric_limits::min()) - { - __err |= ios_base::failbit; - __n = numeric_limits::min(); - } - else if (__temp > numeric_limits::max()) - { - __err |= ios_base::failbit; - __n = numeric_limits::max(); - } - else - __n = static_cast(__temp); - this->setstate(__err); - } -#ifndef _LIBCPP_NO_EXCEPTIONS - } - catch (...) - { - this->__set_badbit_and_consider_rethrow(); - } -#endif // _LIBCPP_NO_EXCEPTIONS - return *this; + return _VSTD::__input_arithmetic_with_numeric_limits(*this, __n); } template -- GitLab From 81872e95bf6507ac88866b1b0f588416b2b2330c Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 20:51:49 +0000 Subject: [PATCH 083/495] [libc++] Use __int128_t to represent file_time_type. Summary: The ``file_time_type`` time point is used to represent the write times for files. Its job is to act as part of a C++ wrapper for less ideal system interfaces. The underlying filesystem uses the ``timespec`` struct for the same purpose. However, the initial implementation of ``file_time_type`` could not represent either the range or resolution of ``timespec``, making it unsuitable. Fixing this requires an implementation which uses more than 64 bits to store the time point. I primarily considered two solutions: Using ``__int128_t`` and using a arithmetic emulation of ``timespec``. Each has its pros and cons, and both come with more than one complication. However, after a lot of consideration, I decided on using `__int128_t`. This patch implements that change. Please see the [FileTimeType Design Document](http://libcxx.llvm.org/docs/DesignDocs/FileTimeType.html) for more information. Reviewers: mclow.lists, ldionne, joerg, arthur.j.odwyer, EricWF Reviewed By: EricWF Subscribers: christof, K-ballo, cfe-commits, BillyONeal Differential Revision: https://reviews.llvm.org/D49774 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337960 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/experimental/filesystem | 32 +- src/chrono.cpp | 41 +- .../filesystem/filesystem_common.h | 263 +++++----- src/experimental/filesystem/operations.cpp | 82 +-- src/include/apple_availability.h | 52 ++ .../last_write_time.sh.cpp | 10 +- .../filesystem/convert_file_time.sh.cpp | 180 +++++-- .../file_time_type.pass.cpp | 27 +- .../last_write_time.pass.cpp | 482 ++++++++++++------ 9 files changed, 762 insertions(+), 407 deletions(-) create mode 100644 src/include/apple_availability.h diff --git a/include/experimental/filesystem b/include/experimental/filesystem index 060c7e033..dbc03595d 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -260,7 +260,37 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM -typedef chrono::time_point file_time_type; +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 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 __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 __secs; + return time_point(__secs(__t)); + } +}; + +typedef chrono::time_point<_FilesystemClock> file_time_type; struct _LIBCPP_TYPE_VIS space_info { diff --git a/src/chrono.cpp b/src/chrono.cpp index d0e184ad3..882d50b9d 100644 --- a/src/chrono.cpp +++ b/src/chrono.cpp @@ -11,27 +11,10 @@ #include "cerrno" // errno #include "system_error" // __throw_system_error #include // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME +#include "include/apple_availability.h" -#if (__APPLE__) -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200 -#define _LIBCXX_USE_CLOCK_GETTIME -#endif -#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 100000 -#define _LIBCXX_USE_CLOCK_GETTIME -#endif -#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 100000 -#define _LIBCXX_USE_CLOCK_GETTIME -#endif -#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 30000 -#define _LIBCXX_USE_CLOCK_GETTIME -#endif -#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ -#else -#define _LIBCXX_USE_CLOCK_GETTIME +#if !defined(__APPLE__) +#define _LIBCPP_USE_CLOCK_GETTIME #endif // __APPLE__ #if defined(_LIBCPP_WIN32API) @@ -42,7 +25,7 @@ #include #endif #else -#if !defined(CLOCK_REALTIME) || !defined(_LIBCXX_USE_CLOCK_GETTIME) +#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME) #include // for gettimeofday and timeval #endif // !defined(CLOCK_REALTIME) #endif // defined(_LIBCPP_WIN32API) @@ -92,16 +75,16 @@ system_clock::now() _NOEXCEPT static_cast<__int64>(ft.dwLowDateTime)}; return time_point(duration_cast(d - nt_to_unix_epoch)); #else -#if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) - struct timespec tp; - if (0 != clock_gettime(CLOCK_REALTIME, &tp)) - __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); - return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); +#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) + struct timespec tp; + if (0 != clock_gettime(CLOCK_REALTIME, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); + return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000)); #else timeval tv; gettimeofday(&tv, 0); return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); -#endif // _LIBCXX_USE_CLOCK_GETTIME && CLOCK_REALTIME +#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME #endif } @@ -129,7 +112,7 @@ const bool steady_clock::is_steady; #if defined(__APPLE__) // Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW -#if defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) +#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) steady_clock::time_point steady_clock::now() _NOEXCEPT { @@ -191,7 +174,7 @@ steady_clock::now() _NOEXCEPT static FP fp = init_steady_clock(); return time_point(duration(fp())); } -#endif // defined(_LIBCXX_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) +#endif // defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW) #elif defined(_LIBCPP_WIN32API) diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index 104d0aa7b..7be167460 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -23,33 +23,17 @@ #include -#if (__APPLE__) -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101300 -#define _LIBCXX_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 110000 -#define _LIBCXX_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 110000 -#define _LIBCXX_USE_UTIMENSAT -#endif -#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) -#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 40000 -#define _LIBCXX_USE_UTIMENSAT -#endif -#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ -#else +#include "../../include/apple_availability.h" + +#if !defined(__APPLE__) // We can use the presence of UTIME_OMIT to detect platforms that provide // utimensat. #if defined(UTIME_OMIT) -#define _LIBCXX_USE_UTIMENSAT +#define _LIBCPP_USE_UTIMENSAT +#endif #endif -#endif // __APPLE__ -#if !defined(_LIBCXX_USE_UTIMENSAT) +#if !defined(_LIBCPP_USE_UTIMENSAT) #include // for ::utimes as used in __last_write_time #endif @@ -212,76 +196,119 @@ private: ErrorHandler& operator=(ErrorHandler const&) = delete; }; -namespace time_util { +using chrono::duration; +using chrono::duration_cast; -using namespace chrono; +using TimeSpec = struct ::timespec; +using StatT = struct ::stat; -template ::value> -struct fs_time_util_base { - static constexpr seconds::rep max_seconds = - duration_cast(FileTimeT::duration::max()).count(); - - static constexpr nanoseconds::rep max_nsec = - duration_cast(FileTimeT::duration::max() - - seconds(max_seconds)) +struct time_util_base { + using rep = typename FileTimeT::rep; + using fs_duration = typename FileTimeT::duration; + using fs_seconds = duration; + using fs_nanoseconds = duration; + using fs_microseconds = duration; + + static constexpr rep max_seconds = + duration_cast(FileTimeT::duration::max()).count(); + + static constexpr rep max_nsec = + duration_cast(FileTimeT::duration::max() - + fs_seconds(max_seconds)) .count(); - static constexpr seconds::rep min_seconds = - duration_cast(FileTimeT::duration::min()).count(); + static constexpr rep min_seconds = + duration_cast(FileTimeT::duration::min()).count(); - static constexpr nanoseconds::rep min_nsec_timespec = - duration_cast( - (FileTimeT::duration::min() - seconds(min_seconds)) + seconds(1)) + static constexpr rep min_nsec_timespec = + duration_cast( + (FileTimeT::duration::min() - fs_seconds(min_seconds)) + + fs_seconds(1)) .count(); +private: +#if _LIBCPP_STD_VER > 11 + static constexpr fs_duration get_min_nsecs() { + return duration_cast( + fs_nanoseconds(min_nsec_timespec) - + duration_cast(fs_seconds(1))); + } // Static assert that these values properly round trip. - static_assert((seconds(min_seconds) + - duration_cast(nanoseconds(min_nsec_timespec))) - - duration_cast(seconds(1)) == + static_assert(fs_seconds(min_seconds) + get_min_nsecs() == FileTimeT::duration::min(), - ""); + "value doesn't roundtrip"); + + static constexpr bool check_range() { + // This kinda sucks, but it's what happens when we don't have __int128_t. + if (sizeof(TimeT) == sizeof(rep)) { + typedef duration > Years; + return duration_cast(fs_seconds(max_seconds)) > Years(250) && + duration_cast(fs_seconds(min_seconds)) < Years(-250); + } + return max_seconds >= numeric_limits::max() && + min_seconds <= numeric_limits::min(); + } + static_assert(check_range(), "the representable range is unacceptable small"); +#endif }; -template -struct fs_time_util_base { - static const long long max_seconds; - static const long long max_nsec; - static const long long min_seconds; - static const long long min_nsec_timespec; +template +struct time_util_base { + using rep = typename FileTimeT::rep; + using fs_duration = typename FileTimeT::duration; + using fs_seconds = duration; + using fs_nanoseconds = duration; + using fs_microseconds = duration; + + static const rep max_seconds; + static const rep max_nsec; + static const rep min_seconds; + static const rep min_nsec_timespec; }; -template -const long long fs_time_util_base::max_seconds = - duration_cast(FileTimeT::duration::max()).count(); +template +const typename FileTimeT::rep + time_util_base::max_seconds = + duration_cast(FileTimeT::duration::max()).count(); -template -const long long fs_time_util_base::max_nsec = - duration_cast(FileTimeT::duration::max() - - seconds(max_seconds)) +template +const typename FileTimeT::rep time_util_base::max_nsec = + duration_cast(FileTimeT::duration::max() - + fs_seconds(max_seconds)) .count(); -template -const long long fs_time_util_base::min_seconds = - duration_cast(FileTimeT::duration::min()).count(); +template +const typename FileTimeT::rep + time_util_base::min_seconds = + duration_cast(FileTimeT::duration::min()).count(); -template -const long long fs_time_util_base::min_nsec_timespec = - duration_cast( - (FileTimeT::duration::min() - seconds(min_seconds)) + seconds(1)) - .count(); +template +const typename FileTimeT::rep + time_util_base::min_nsec_timespec = + duration_cast((FileTimeT::duration::min() - + fs_seconds(min_seconds)) + + fs_seconds(1)) + .count(); template -struct fs_time_util : fs_time_util_base { - using Base = fs_time_util_base; +struct time_util : time_util_base { + using Base = time_util_base; using Base::max_nsec; using Base::max_seconds; using Base::min_nsec_timespec; using Base::min_seconds; + using typename Base::fs_duration; + using typename Base::fs_microseconds; + using typename Base::fs_nanoseconds; + using typename Base::fs_seconds; + public: template - static bool checked_set(CType* out, ChronoType time) { + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool checked_set(CType* out, + ChronoType time) { using Lim = numeric_limits; if (time > Lim::max() || time < Lim::min()) return false; @@ -291,21 +318,21 @@ public: static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(TimeSpecT tm) { if (tm.tv_sec >= 0) { - return (tm.tv_sec < max_seconds) || + return tm.tv_sec < max_seconds || (tm.tv_sec == max_seconds && tm.tv_nsec <= max_nsec); } else if (tm.tv_sec == (min_seconds - 1)) { return tm.tv_nsec >= min_nsec_timespec; } else { - return (tm.tv_sec >= min_seconds); + return tm.tv_sec >= min_seconds; } } static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool is_representable(FileTimeT tm) { - auto secs = duration_cast(tm.time_since_epoch()); - auto nsecs = duration_cast(tm.time_since_epoch() - secs); + auto secs = duration_cast(tm.time_since_epoch()); + auto nsecs = duration_cast(tm.time_since_epoch() - secs); if (nsecs.count() < 0) { - secs = secs + seconds(1); - nsecs = nsecs + seconds(1); + secs = secs + fs_seconds(1); + nsecs = nsecs + fs_seconds(1); } using TLim = numeric_limits; if (secs.count() >= 0) @@ -314,49 +341,45 @@ public: } static _LIBCPP_CONSTEXPR_AFTER_CXX11 FileTimeT - convert_timespec(TimeSpecT tm) { - auto adj_msec = duration_cast(nanoseconds(tm.tv_nsec)); - if (tm.tv_sec >= 0) { - auto Dur = seconds(tm.tv_sec) + microseconds(adj_msec); - return FileTimeT(Dur); - } else if (duration_cast(nanoseconds(tm.tv_nsec)).count() == - 0) { - return FileTimeT(seconds(tm.tv_sec)); + convert_from_timespec(TimeSpecT tm) { + if (tm.tv_sec >= 0 || tm.tv_nsec == 0) { + return FileTimeT(fs_seconds(tm.tv_sec) + + duration_cast(fs_nanoseconds(tm.tv_nsec))); } else { // tm.tv_sec < 0 - auto adj_subsec = - duration_cast(seconds(1) - nanoseconds(tm.tv_nsec)); - auto Dur = seconds(tm.tv_sec + 1) - adj_subsec; + auto adj_subsec = duration_cast(fs_seconds(1) - + fs_nanoseconds(tm.tv_nsec)); + auto Dur = fs_seconds(tm.tv_sec + 1) - adj_subsec; return FileTimeT(Dur); } } - template - static bool set_times_checked(TimeT* sec_out, SubSecT* subsec_out, - FileTimeT tp) { + template + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool + set_times_checked(TimeT* sec_out, SubSecT* subsec_out, FileTimeT tp) { auto dur = tp.time_since_epoch(); - auto sec_dur = duration_cast(dur); - auto subsec_dur = duration_cast(dur - sec_dur); + auto sec_dur = duration_cast(dur); + auto subsec_dur = duration_cast(dur - sec_dur); // The tv_nsec and tv_usec fields must not be negative so adjust accordingly if (subsec_dur.count() < 0) { if (sec_dur.count() > min_seconds) { - sec_dur -= seconds(1); - subsec_dur += seconds(1); + sec_dur -= fs_seconds(1); + subsec_dur += fs_seconds(1); } else { - subsec_dur = SubSecDurT::zero(); + subsec_dur = fs_nanoseconds::zero(); } } return checked_set(sec_out, sec_dur.count()) && checked_set(subsec_out, subsec_dur.count()); } + static _LIBCPP_CONSTEXPR_AFTER_CXX11 bool convert_to_timespec(TimeSpecT& dest, + FileTimeT tp) { + if (!is_representable(tp)) + return false; + return set_times_checked(&dest.tv_sec, &dest.tv_nsec, tp); + } }; -} // namespace time_util - - -using TimeSpec = struct ::timespec; -using StatT = struct ::stat; - -using FSTime = time_util::fs_time_util; +using fs_time = time_util; #if defined(__APPLE__) TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; } @@ -366,20 +389,18 @@ TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } TimeSpec extract_atime(StatT const& st) { return st.st_atim; } #endif -#if !defined(_LIBCXX_USE_UTIMENSAT) -using TimeStruct = struct ::timeval; -using TimeStructArray = TimeStruct[2]; -#else -using TimeStruct = TimeSpec; -using TimeStructArray = TimeStruct[2]; -#endif - -bool SetFileTimes(const path& p, TimeStructArray const& TS, - error_code& ec) { -#if !defined(_LIBCXX_USE_UTIMENSAT) - if (::utimes(p.c_str(), TS) == -1) +bool set_file_times(const path& p, std::array const& TS, + error_code& ec) { +#if !defined(_LIBCPP_USE_UTIMENSAT) + using namespace chrono; + auto Convert = [](long nsec) { + return duration_cast(nanoseconds(nsec)).count(); + }; + struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)}, + {TS[1].tv_sec, Convert(TS[1].tv_nsec)}}; + if (::utimes(p.c_str(), ConvertedTS) == -1) #else - if (::utimensat(AT_FDCWD, p.c_str(), TS, 0) == -1) + if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) #endif { ec = capture_errno(); @@ -388,25 +409,9 @@ bool SetFileTimes(const path& p, TimeStructArray const& TS, return false; } -void SetTimeStructTo(TimeStruct& TS, TimeSpec ToTS) { - using namespace chrono; - TS.tv_sec = ToTS.tv_sec; -#if !defined(_LIBCXX_USE_UTIMENSAT) - TS.tv_usec = duration_cast(nanoseconds(ToTS.tv_nsec)).count(); -#else - TS.tv_nsec = ToTS.tv_nsec; -#endif -} - -bool SetTimeStructTo(TimeStruct& TS, file_time_type NewTime) { - using namespace chrono; -#if !defined(_LIBCXX_USE_UTIMENSAT) - return !FSTime::set_times_checked(&TS.tv_sec, &TS.tv_usec, - NewTime); -#else - return !FSTime::set_times_checked(&TS.tv_sec, &TS.tv_nsec, - NewTime); -#endif +bool set_time_spec_to(TimeSpec& TS, file_time_type NewTime) { + return !fs_time::set_times_checked( + &TS.tv_sec, &TS.tv_nsec, NewTime); } } // namespace diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index dd8b43477..d57066875 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include /* values for fchmodat */ #if defined(__linux__) @@ -36,6 +37,14 @@ # define _LIBCPP_USE_COPYFILE #endif +#if !defined(__APPLE__) +#define _LIBCPP_USE_CLOCK_GETTIME +#endif + +#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME) +#include // for gettimeofday and timeval +#endif // !defined(CLOCK_REALTIME) + #if defined(_LIBCPP_COMPILER_GCC) #if _GNUC_VER < 500 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" @@ -44,9 +53,6 @@ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM -filesystem_error::~filesystem_error() {} - - namespace { namespace parser { @@ -355,7 +361,7 @@ private: explicit FileDescriptor(const path* p, int fd = -1) : name(*p), fd(fd) {} }; -perms posix_get_perms(const struct ::stat& st) noexcept { +perms posix_get_perms(const StatT& st) noexcept { return static_cast(st.st_mode) & perms::mask; } @@ -364,8 +370,7 @@ perms posix_get_perms(const struct ::stat& st) noexcept { } file_status create_file_status(error_code& m_ec, path const& p, - const struct ::stat& path_stat, - error_code* ec) { + const StatT& path_stat, error_code* ec) { if (ec) *ec = m_ec; if (m_ec && (m_ec.value() == ENOENT || m_ec.value() == ENOTDIR)) { @@ -400,8 +405,7 @@ file_status create_file_status(error_code& m_ec, path const& p, return fs_tmp; } -file_status posix_stat(path const& p, struct ::stat& path_stat, - error_code* ec) { +file_status posix_stat(path const& p, StatT& path_stat, error_code* ec) { error_code m_ec; if (::stat(p.c_str(), &path_stat) == -1) m_ec = detail::capture_errno(); @@ -409,12 +413,11 @@ file_status posix_stat(path const& p, struct ::stat& path_stat, } file_status posix_stat(path const& p, error_code* ec) { - struct ::stat path_stat; + StatT path_stat; return posix_stat(p, path_stat, ec); } -file_status posix_lstat(path const& p, struct ::stat& path_stat, - error_code* ec) { +file_status posix_lstat(path const& p, StatT& path_stat, error_code* ec) { error_code m_ec; if (::lstat(p.c_str(), &path_stat) == -1) m_ec = detail::capture_errno(); @@ -422,7 +425,7 @@ file_status posix_lstat(path const& p, struct ::stat& path_stat, } file_status posix_lstat(path const& p, error_code* ec) { - struct ::stat path_stat; + StatT path_stat; return posix_lstat(p, path_stat, ec); } @@ -464,10 +467,32 @@ file_status FileDescriptor::refresh_status(error_code& ec) { using detail::capture_errno; using detail::ErrorHandler; using detail::StatT; +using detail::TimeSpec; using parser::createView; using parser::PathParser; using parser::string_view_t; +const bool _FilesystemClock::is_steady; + +_FilesystemClock::time_point _FilesystemClock::now() noexcept { + typedef chrono::duration __secs; +#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) + typedef chrono::duration __nsecs; + struct timespec tp; + if (0 != clock_gettime(CLOCK_REALTIME, &tp)) + __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed"); + return time_point(__secs(tp.tv_sec) + + chrono::duration_cast(__nsecs(tp.tv_nsec))); +#else + typedef chrono::duration __microsecs; + timeval tv; + gettimeofday(&tv, 0); + return time_point(__secs(tv.tv_sec) + __microsecs(tv.tv_usec)); +#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME +} + +filesystem_error::~filesystem_error() {} + void filesystem_error::__create_what(int __num_paths) { const char* derived_what = system_error::what(); __storage_->__what_ = [&]() -> string { @@ -525,14 +550,14 @@ void __copy(const path& from, const path& to, copy_options options, const bool sym_status2 = bool(options & copy_options::copy_symlinks); error_code m_ec1; - struct ::stat f_st = {}; + StatT f_st = {}; const file_status f = sym_status || sym_status2 ? detail::posix_lstat(from, f_st, &m_ec1) : detail::posix_stat(from, f_st, &m_ec1); if (m_ec1) return err.report(m_ec1); - struct ::stat t_st = {}; + StatT t_st = {}; const file_status t = sym_status ? detail::posix_lstat(to, t_st, &m_ec1) : detail::posix_stat(to, t_st, &m_ec1); @@ -916,7 +941,7 @@ uintmax_t __file_size(const path& p, error_code *ec) ErrorHandler err("file_size", ec, &p); error_code m_ec; - struct ::stat st; + StatT st; file_status fst = detail::posix_stat(p, st, &m_ec); if (!exists(fst) || !is_regular_file(fst)) { errc error_kind = @@ -966,14 +991,14 @@ bool __fs_is_empty(const path& p, error_code *ec) static file_time_type __extract_last_write_time(const path& p, const StatT& st, error_code* ec) { - using detail::FSTime; + using detail::fs_time; ErrorHandler err("last_write_time", ec, &p); auto ts = detail::extract_mtime(st); - if (!FSTime::is_representable(ts)) + if (!fs_time::is_representable(ts)) return err.report(errc::value_too_large); - return FSTime::convert_timespec(ts); + return fs_time::convert_from_timespec(ts); } file_time_type __last_write_time(const path& p, error_code *ec) @@ -992,30 +1017,27 @@ file_time_type __last_write_time(const path& p, error_code *ec) void __last_write_time(const path& p, file_time_type new_time, error_code *ec) { - using namespace chrono; - using namespace detail; - ErrorHandler err("last_write_time", ec, &p); error_code m_ec; - TimeStructArray tbuf; -#if !defined(_LIBCXX_USE_UTIMENSAT) + array tbuf; +#if !defined(_LIBCPP_USE_UTIMENSAT) // This implementation has a race condition between determining the // last access time and attempting to set it to the same value using // ::utimes - struct ::stat st; + StatT st; file_status fst = detail::posix_stat(p, st, &m_ec); - if (m_ec && !status_known(fst)) + if (m_ec) return err.report(m_ec); - SetTimeStructTo(tbuf[0], detail::extract_atime(st)); + tbuf[0] = detail::extract_atime(st); #else tbuf[0].tv_sec = 0; tbuf[0].tv_nsec = UTIME_OMIT; #endif - if (SetTimeStructTo(tbuf[1], new_time)) - return err.report(errc::invalid_argument); + if (detail::set_time_spec_to(tbuf[1], new_time)) + return err.report(errc::value_too_large); - SetFileTimes(p, tbuf, m_ec); + detail::set_file_times(p, tbuf, m_ec); if (m_ec) return err.report(m_ec); } @@ -1591,7 +1613,7 @@ error_code directory_entry::__do_refresh() noexcept { __data_.__reset(); error_code failure_ec; - struct ::stat full_st; + StatT full_st; file_status st = detail::posix_lstat(__p_, full_st, &failure_ec); if (!status_known(st)) { __data_.__reset(); diff --git a/src/include/apple_availability.h b/src/include/apple_availability.h new file mode 100644 index 000000000..c12f7325c --- /dev/null +++ b/src/include/apple_availability.h @@ -0,0 +1,52 @@ +//===------------------------ apple_availability.h ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H +#define _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H + +#if defined(__APPLE__) + +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101300 +#define _LIBCPP_USE_UTIMENSAT +#endif +#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 110000 +#define _LIBCPP_USE_UTIMENSAT +#endif +#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 110000 +#define _LIBCPP_USE_UTIMENSAT +#endif +#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 40000 +#define _LIBCPP_USE_UTIMENSAT +#endif +#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ + +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101200 +#define _LIBCPP_USE_CLOCK_GETTIME +#endif +#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 100000 +#define _LIBCPP_USE_CLOCK_GETTIME +#endif +#elif defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 100000 +#define _LIBCPP_USE_CLOCK_GETTIME +#endif +#elif defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) +#if __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 30000 +#define _LIBCPP_USE_CLOCK_GETTIME +#endif +#endif // __ENVIRONMENT_.*_VERSION_MIN_REQUIRED__ + +#endif // __APPLE__ + +#endif // _LIBCPP_SRC_INCLUDE_APPLE_AVAILABILITY_H diff --git a/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp b/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp index 2305f54f5..7f4ed6730 100644 --- a/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp +++ b/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp @@ -41,9 +41,7 @@ TEST_CASE(last_write_time_not_representable_error) { ToTime.tv_sec = std::numeric_limits::max(); ToTime.tv_nsec = duration_cast(seconds(1)).count() - 1; - TimeStructArray TS; - SetTimeStructTo(TS[0], ToTime); - SetTimeStructTo(TS[1], ToTime); + std::array TS = {ToTime, ToTime}; file_time_type old_time = last_write_time(file); directory_entry ent(file); @@ -57,9 +55,7 @@ TEST_CASE(last_write_time_not_representable_error) { file_time_type rep_value; { std::error_code ec; - if (SetFileTimes(file, TS, ec)) { - TEST_REQUIRE(false && "unsupported"); - } + TEST_REQUIRE(!set_file_times(file, TS, ec)); ec.clear(); rep_value = last_write_time(file, ec); IsRepresentable = !bool(ec); @@ -82,7 +78,7 @@ TEST_CASE(last_write_time_not_representable_error) { ExceptionChecker CheckExcept(file, expected_err, "directory_entry::last_write_time"); - TEST_CHECK_THROW_RESULT(fs::filesystem_error, CheckExcept, + TEST_CHECK_THROW_RESULT(filesystem_error, CheckExcept, ent.last_write_time()); } else { diff --git a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp b/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp index cc1696cea..4c18eedc6 100644 --- a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp +++ b/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp @@ -25,15 +25,23 @@ #include "filesystem_common.h" +#ifndef __SIZEOF_INT128__ +#define TEST_HAS_NO_INT128_T +#endif + using namespace std::chrono; namespace fs = std::experimental::filesystem; using fs::file_time_type; -using fs::detail::time_util::fs_time_util; +using fs::detail::time_util; + +#ifdef TEST_HAS_NO_INT128_T +static_assert(sizeof(fs::file_time_type::rep) <= 8, ""); +#endif -enum TestKind { TK_64Bit, TK_32Bit, TK_FloatingPoint }; +enum TestKind { TK_128Bit, TK_64Bit, TK_32Bit, TK_FloatingPoint }; -template -constexpr TestKind getTestKind() { +template +constexpr TestKind getTimeTTestKind() { if (sizeof(TimeT) == 8 && !std::is_floating_point::value) return TK_64Bit; else if (sizeof(TimeT) == 4 && !std::is_floating_point::value) @@ -43,17 +51,99 @@ constexpr TestKind getTestKind() { else assert(false && "test kind not supported"); } +template +constexpr TestKind getFileTimeTestKind() { + using Rep = typename FileTimeT::rep; + if (std::is_floating_point::value) + return TK_FloatingPoint; + if (sizeof(Rep) == 16) + return TK_128Bit; + if (sizeof(Rep) == 8) + return TK_64Bit; + assert(false && "test kind not supported"); +} template , - TestKind = getTestKind()> -struct check_is_representable; + class Base = time_util, + TestKind = getTimeTTestKind(), + TestKind = getFileTimeTestKind()> +struct test_case; template -struct check_is_representable +struct test_case : public Base { - using Base::convert_timespec; + using Base::convert_from_timespec; + using Base::convert_to_timespec; + using Base::is_representable; + using Base::max_nsec; + using Base::max_seconds; + using Base::min_nsec_timespec; + using Base::min_seconds; + + static constexpr auto max_time_t = std::numeric_limits::max(); + static constexpr auto min_time_t = std::numeric_limits::min(); + + static constexpr bool test_timespec() { + static_assert(is_representable(TimeSpecT{max_time_t, 0}), ""); + static_assert(is_representable(TimeSpecT{max_time_t, 999999999}), ""); + static_assert(is_representable(TimeSpecT{max_time_t, 1000000000}), ""); + static_assert(is_representable(TimeSpecT{max_time_t, max_nsec}), ""); + + static_assert(is_representable(TimeSpecT{min_time_t, 0}), ""); + static_assert(is_representable(TimeSpecT{min_time_t, 999999999}), ""); + static_assert(is_representable(TimeSpecT{min_time_t, 1000000000}), ""); + static_assert(is_representable(TimeSpecT{min_time_t, min_nsec_timespec}), + ""); + + return true; + } + + static constexpr bool test_file_time_type() { + // This kinda sucks. Oh well. + static_assert(!Base::is_representable(FileTimeT::max()), ""); + static_assert(!Base::is_representable(FileTimeT::min()), ""); + return true; + } + + static constexpr bool check_round_trip(TimeSpecT orig) { + TimeSpecT new_ts = {}; + FileTimeT out = convert_from_timespec(orig); + assert(convert_to_timespec(new_ts, out)); + return new_ts.tv_sec == orig.tv_sec && new_ts.tv_nsec == orig.tv_nsec; + } + + static constexpr bool test_convert_timespec() { + static_assert(check_round_trip({0, 0}), ""); + static_assert(check_round_trip({0, 1}), ""); + static_assert(check_round_trip({1, 1}), ""); + static_assert(check_round_trip({-1, 1}), ""); + static_assert(check_round_trip({max_time_t, max_nsec}), ""); + static_assert(check_round_trip({max_time_t, 123}), ""); + static_assert(check_round_trip({min_time_t, min_nsec_timespec}), ""); + static_assert(check_round_trip({min_time_t, 123}), ""); + return true; + } + + static bool test() { + static_assert(test_timespec(), ""); + static_assert(test_file_time_type(), ""); + static_assert(test_convert_timespec(), ""); + return true; + } +}; + +template +struct test_case + : public test_case { + +}; + +template +struct test_case + : public Base { + + using Base::convert_from_timespec; using Base::is_representable; using Base::max_nsec; using Base::max_seconds; @@ -88,24 +178,25 @@ struct check_is_representable } static constexpr bool test_convert_timespec() { - static_assert(convert_timespec(TimeSpecT{max_seconds, max_nsec}) == + static_assert(convert_from_timespec(TimeSpecT{max_seconds, max_nsec}) == FileTimeT::max(), ""); - static_assert(convert_timespec(TimeSpecT{max_seconds, max_nsec - 1}) < + static_assert(convert_from_timespec(TimeSpecT{max_seconds, max_nsec - 1}) < FileTimeT::max(), ""); - static_assert(convert_timespec(TimeSpecT{max_seconds - 1, 999999999}) < + static_assert(convert_from_timespec(TimeSpecT{max_seconds - 1, 999999999}) < FileTimeT::max(), ""); - static_assert(convert_timespec(TimeSpecT{ + static_assert(convert_from_timespec(TimeSpecT{ min_seconds - 1, min_nsec_timespec}) == FileTimeT::min(), ""); - static_assert( - convert_timespec(TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}) > - FileTimeT::min(), - ""); - static_assert( - convert_timespec(TimeSpecT{min_seconds, 0}) > FileTimeT::min(), ""); + static_assert(convert_from_timespec( + TimeSpecT{min_seconds - 1, min_nsec_timespec + 1}) > + FileTimeT::min(), + ""); + static_assert(convert_from_timespec(TimeSpecT{min_seconds, 0}) > + FileTimeT::min(), + ""); return true; } @@ -118,12 +209,12 @@ struct check_is_representable }; template -struct check_is_representable +struct test_case : public Base { static constexpr auto max_time_t = std::numeric_limits::max(); static constexpr auto min_time_t = std::numeric_limits::min(); - using Base::convert_timespec; + using Base::convert_from_timespec; using Base::is_representable; using Base::max_nsec; using Base::max_seconds; @@ -158,9 +249,10 @@ struct check_is_representable } }; -template -struct check_is_representable : public Base { +template +struct test_case : public Base { static bool test() { return true; } }; @@ -182,19 +274,33 @@ struct TestClock { static time_point now() noexcept { return {}; } }; -template > -using TestFileTimeT = time_point >; +template +using TestFileTimeT = time_point > >; int main() { - assert(( - check_is_representable::test())); - assert((check_is_representable, int64_t, - TestTimeSpec >::test())); - assert((check_is_representable, int32_t, - TestTimeSpec >::test())); - - // Test that insane platforms like ppc64 linux, which use long double as time_t, - // at least compile. - assert((check_is_representable, double, - TestTimeSpec >::test())); + { assert((test_case::test())); } + { + assert((test_case, int64_t, + TestTimeSpec >::test())); + } + { + assert((test_case, int32_t, + TestTimeSpec >::test())); + } + { + // Test that insane platforms like ppc64 linux, which use long double as time_t, + // at least compile. + assert((test_case, double, + TestTimeSpec >::test())); + } +#ifndef TEST_HAS_NO_INT128_T + { + assert((test_case, int64_t, + TestTimeSpec >::test())); + } + { + assert((test_case, int32_t, + TestTimeSpec >::test())); + } +#endif } diff --git a/test/std/experimental/filesystem/fs.filesystem.synopsis/file_time_type.pass.cpp b/test/std/experimental/filesystem/fs.filesystem.synopsis/file_time_type.pass.cpp index 62a0e74a1..1c25450da 100644 --- a/test/std/experimental/filesystem/fs.filesystem.synopsis/file_time_type.pass.cpp +++ b/test/std/experimental/filesystem/fs.filesystem.synopsis/file_time_type.pass.cpp @@ -17,15 +17,30 @@ #include #include +#include "test_macros.h" + // system_clock is used because it meets the requirements of TrivialClock, // and the resolution and range of system_clock should match the operating // system's file time type. -typedef std::chrono::system_clock ExpectedClock; -typedef std::chrono::time_point ExpectedTimePoint; + +void test_trivial_clock() { + using namespace fs; + using Clock = file_time_type::clock; + ASSERT_NOEXCEPT(Clock::now()); + ASSERT_SAME_TYPE(decltype(Clock::now()), file_time_type); + ASSERT_SAME_TYPE(Clock::time_point, file_time_type); + volatile auto* odr_use = &Clock::is_steady; + ((void)odr_use); +} + +void test_time_point_resolution_and_range() { + using namespace fs; + using Dur = file_time_type::duration; + using Period = Dur::period; + ASSERT_SAME_TYPE(Period, std::nano); +} int main() { - static_assert(std::is_same< - fs::file_time_type, - ExpectedTimePoint - >::value, ""); + test_trivial_clock(); + test_time_point_resolution_and_range(); } diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp index a515b990a..b216c5f17 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -30,13 +30,86 @@ #include #include +#include +#include + using namespace fs; -struct Times { std::time_t access, write; }; +using TimeSpec = struct ::timespec; +using StatT = struct ::stat; + +using Sec = std::chrono::duration; +using Hours = std::chrono::hours; +using Minutes = std::chrono::minutes; +using MicroSec = std::chrono::duration; +using NanoSec = std::chrono::duration; +using std::chrono::duration_cast; + +#if defined(__APPLE__) +TimeSpec extract_mtime(StatT const& st) { return st.st_mtimespec; } +TimeSpec extract_atime(StatT const& st) { return st.st_atimespec; } +#else +TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } +TimeSpec extract_atime(StatT const& st) { return st.st_atim; } +#endif + +bool ConvertToTimeSpec(TimeSpec& ts, file_time_type ft) { + using SecFieldT = decltype(TimeSpec::tv_sec); + using NSecFieldT = decltype(TimeSpec::tv_nsec); + using SecLim = std::numeric_limits; + using NSecLim = std::numeric_limits; + + auto secs = duration_cast(ft.time_since_epoch()); + auto nsecs = duration_cast(ft.time_since_epoch() - secs); + if (nsecs.count() < 0) { + if (Sec::min().count() > SecLim::min()) { + secs += Sec(1); + nsecs -= Sec(1); + } else { + nsecs = NanoSec(0); + } + } + if (SecLim::max() < secs.count() || SecLim::min() > secs.count()) + return false; + if (NSecLim::max() < nsecs.count() || NSecLim::min() > nsecs.count()) + return false; + ts.tv_sec = secs.count(); + ts.tv_nsec = nsecs.count(); + return true; +} + +bool ConvertFromTimeSpec(file_time_type& ft, TimeSpec ts) { + auto secs_part = duration_cast(Sec(ts.tv_sec)); + if (duration_cast(secs_part).count() != ts.tv_sec) + return false; + auto subsecs = duration_cast(NanoSec(ts.tv_nsec)); + auto dur = secs_part + subsecs; + if (dur < secs_part && subsecs.count() >= 0) + return false; + ft = file_time_type(dur); + return true; +} + +bool CompareTimeExact(TimeSpec ts, TimeSpec ts2) { + return ts2.tv_sec == ts.tv_sec && ts2.tv_nsec == ts.tv_nsec; +} +bool CompareTimeExact(file_time_type ft, TimeSpec ts) { + TimeSpec ts2 = {}; + if (!ConvertToTimeSpec(ts2, ft)) + return false; + return CompareTimeExact(ts, ts2); +} +bool CompareTimeExact(TimeSpec ts, file_time_type ft) { + return CompareTimeExact(ft, ts); +} + +struct Times { + TimeSpec access, write; +}; Times GetTimes(path const& p) { using Clock = file_time_type::clock; - struct ::stat st; + StatT st; if (::stat(p.c_str(), &st) == -1) { std::error_code ec(errno, std::generic_category()); #ifndef TEST_HAS_NO_EXCEPTIONS @@ -46,22 +119,18 @@ Times GetTimes(path const& p) { std::exit(EXIT_FAILURE); #endif } - return {st.st_atime, st.st_mtime}; + return {extract_atime(st), extract_mtime(st)}; } -std::time_t LastAccessTime(path const& p) { - return GetTimes(p).access; -} +TimeSpec LastAccessTime(path const& p) { return GetTimes(p).access; } -std::time_t LastWriteTime(path const& p) { - return GetTimes(p).write; -} +TimeSpec LastWriteTime(path const& p) { return GetTimes(p).write; } -std::pair GetSymlinkTimes(path const& p) { - using Clock = file_time_type::clock; - struct ::stat st; - if (::lstat(p.c_str(), &st) == -1) { - std::error_code ec(errno, std::generic_category()); +std::pair GetSymlinkTimes(path const& p) { + using Clock = file_time_type::clock; + StatT st; + if (::lstat(p.c_str(), &st) == -1) { + std::error_code ec(errno, std::generic_category()); #ifndef TEST_HAS_NO_EXCEPTIONS throw ec; #else @@ -69,24 +138,10 @@ std::pair GetSymlinkTimes(path const& p) { std::exit(EXIT_FAILURE); #endif } - return {st.st_atime, st.st_mtime}; + return {extract_atime(st), extract_mtime(st)}; } namespace { -bool TestSupportsNegativeTimes() { - using namespace std::chrono; - std::error_code ec; - std::time_t old_write_time, new_write_time; - { // WARNING: Do not assert in this scope. - scoped_test_env env; - const path file = env.create_file("file", 42); - old_write_time = LastWriteTime(file); - file_time_type tp(seconds(-5)); - fs::last_write_time(file, tp, ec); - new_write_time = LastWriteTime(file); - } - return !ec && new_write_time <= -5; -} // In some configurations, the comparison is tautological and the test is valid. // We disable the warning so that we can actually test it regardless. Also, that @@ -98,61 +153,131 @@ bool TestSupportsNegativeTimes() { #pragma clang diagnostic ignored "-Wtautological-constant-compare" #endif -bool TestSupportsMaxTime() { - using namespace std::chrono; - using Lim = std::numeric_limits; - auto max_sec = duration_cast(file_time_type::max().time_since_epoch()).count(); - if (max_sec > Lim::max()) return false; - std::error_code ec; - std::time_t old_write_time, new_write_time; - { // WARNING: Do not assert in this scope. - scoped_test_env env; - const path file = env.create_file("file", 42); - old_write_time = LastWriteTime(file); - file_time_type tp = file_time_type::max(); - fs::last_write_time(file, tp, ec); - new_write_time = LastWriteTime(file); - } - return !ec && new_write_time > max_sec - 1; -} +static const bool SupportsNegativeTimes = [] { + using namespace std::chrono; + std::error_code ec; + TimeSpec old_write_time, new_write_time; + { // WARNING: Do not assert in this scope. + scoped_test_env env; + const path file = env.create_file("file", 42); + old_write_time = LastWriteTime(file); + file_time_type tp(seconds(-5)); + fs::last_write_time(file, tp, ec); + new_write_time = LastWriteTime(file); + } + + return !ec && new_write_time.tv_sec < 0; +}(); + +static const bool SupportsMaxTime = [] { + using namespace std::chrono; + TimeSpec max_ts = {}; + if (!ConvertToTimeSpec(max_ts, file_time_type::max())) + return false; + + std::error_code ec; + TimeSpec old_write_time, new_write_time; + { // WARNING: Do not assert in this scope. + scoped_test_env env; + const path file = env.create_file("file", 42); + old_write_time = LastWriteTime(file); + file_time_type tp = file_time_type::max(); + fs::last_write_time(file, tp, ec); + new_write_time = LastWriteTime(file); + } + return !ec && new_write_time.tv_sec > max_ts.tv_sec - 1; +}(); + +static const bool SupportsMinTime = [] { + using namespace std::chrono; + TimeSpec min_ts = {}; + if (!ConvertToTimeSpec(min_ts, file_time_type::min())) + return false; + std::error_code ec; + TimeSpec old_write_time, new_write_time; + { // WARNING: Do not assert in this scope. + scoped_test_env env; + const path file = env.create_file("file", 42); + old_write_time = LastWriteTime(file); + file_time_type tp = file_time_type::min(); + fs::last_write_time(file, tp, ec); + new_write_time = LastWriteTime(file); + } + return !ec && new_write_time.tv_sec < min_ts.tv_sec + 1; +}(); + +static const bool SupportsNanosecondRoundTrip = [] { + NanoSec ns(3); + + // Test if the file_time_type period is less than that of nanoseconds. + auto ft_dur = duration_cast(ns); + if (duration_cast(ft_dur) != ns) + return false; + + // Test that the system call we use to set the times also supports nanosecond + // resolution. (utimes does not) + file_time_type ft(ft_dur); + { + scoped_test_env env; + const path p = env.create_file("file", 42); + last_write_time(p, ft); + return last_write_time(p) == ft; + } +}(); + +static const bool SupportsMinRoundTrip = [] { + TimeSpec ts = {}; + if (!ConvertToTimeSpec(ts, file_time_type::min())) + return false; + file_time_type min_val = {}; + if (!ConvertFromTimeSpec(min_val, ts)) + return false; + return min_val == file_time_type::min(); +}(); -bool TestSupportsMinTime() { - using namespace std::chrono; - using Lim = std::numeric_limits; - auto min_sec = duration_cast(file_time_type::min().time_since_epoch()).count(); - if (min_sec < Lim::min()) return false; - std::error_code ec; - std::time_t old_write_time, new_write_time; - { // WARNING: Do not assert in this scope. - scoped_test_env env; - const path file = env.create_file("file", 42); - old_write_time = LastWriteTime(file); - file_time_type tp = file_time_type::min(); - fs::last_write_time(file, tp, ec); - new_write_time = LastWriteTime(file); - } - return !ec && new_write_time < min_sec + 1; -} +} // end namespace -#if defined(__clang__) -#pragma clang diagnostic pop -#endif +static bool CompareTime(TimeSpec t1, TimeSpec t2) { + if (SupportsNanosecondRoundTrip) + return CompareTimeExact(t1, t2); + if (t1.tv_sec != t2.tv_sec) + return false; -static const bool SupportsNegativeTimes = TestSupportsNegativeTimes(); -static const bool SupportsMaxTime = TestSupportsMaxTime(); -static const bool SupportsMinTime = TestSupportsMinTime(); + auto diff = std::abs(t1.tv_nsec - t2.tv_nsec); -} // end namespace + return diff < duration_cast(MicroSec(1)).count(); +} -// In some configurations, the comparison is tautological and the test is valid. -// We disable the warning so that we can actually test it regardless. Also, that -// diagnostic is pretty new, so also don't fail if old clang does not support it -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunknown-warning-option" -#pragma clang diagnostic ignored "-Wunknown-pragmas" -#pragma clang diagnostic ignored "-Wtautological-constant-compare" -#endif +static bool CompareTime(file_time_type t1, TimeSpec t2) { + TimeSpec ts1 = {}; + if (!ConvertToTimeSpec(ts1, t1)) + return false; + return CompareTime(ts1, t2); +} + +static bool CompareTime(TimeSpec t1, file_time_type t2) { + return CompareTime(t2, t1); +} + +static bool CompareTime(file_time_type t1, file_time_type t2) { + auto min_secs = duration_cast(file_time_type::min().time_since_epoch()); + bool IsMin = + t1.time_since_epoch() < min_secs || t2.time_since_epoch() < min_secs; + + if (SupportsNanosecondRoundTrip && (!IsMin || SupportsMinRoundTrip)) + return t1 == t2; + if (IsMin) { + return duration_cast(t1.time_since_epoch()) == + duration_cast(t2.time_since_epoch()); + } + file_time_type::duration dur; + if (t1 > t2) + dur = t1 - t2; + else + dur = t2 - t1; + + return duration_cast(dur).count() < 1; +} // Check if a time point is representable on a given filesystem. Check that: // (A) 'tp' is representable as a time_t @@ -162,22 +287,33 @@ static const bool SupportsMinTime = TestSupportsMinTime(); // (D) 'tp' is not 'file_time_type::min()' or the filesystem supports the min // value. inline bool TimeIsRepresentableByFilesystem(file_time_type tp) { - using namespace std::chrono; - using Lim = std::numeric_limits; - auto sec = duration_cast(tp.time_since_epoch()).count(); - auto microsec = duration_cast(tp.time_since_epoch()).count(); - if (sec < Lim::min() || sec > Lim::max()) return false; - else if (microsec < 0 && !SupportsNegativeTimes) return false; - else if (tp == file_time_type::max() && !SupportsMaxTime) return false; - else if (tp == file_time_type::min() && !SupportsMinTime) return false; - return true; + TimeSpec ts = {}; + if (!ConvertToTimeSpec(ts, tp)) + return false; + else if (tp.time_since_epoch().count() < 0 && !SupportsNegativeTimes) + return false; + else if (tp == file_time_type::max() && !SupportsMaxTime) + return false; + else if (tp == file_time_type::min() && !SupportsMinTime) + return false; + return true; } #if defined(__clang__) #pragma clang diagnostic pop #endif -TEST_SUITE(exists_test_suite) +// Create a sub-second duration using the smallest period the filesystem supports. +file_time_type::duration SubSec(long long val) { + using SubSecT = file_time_type::duration; + if (SupportsNanosecondRoundTrip) { + return duration_cast(NanoSec(val)); + } else { + return duration_cast(MicroSec(val)); + } +} + +TEST_SUITE(last_write_time_test_suite) TEST_CASE(signature_test) { @@ -202,21 +338,21 @@ TEST_CASE(read_last_write_time_static_env_test) file_time_type ret = last_write_time(StaticEnv::File); TEST_CHECK(ret != min); TEST_CHECK(ret < C::now()); - TEST_CHECK(C::to_time_t(ret) == LastWriteTime(StaticEnv::File)); + TEST_CHECK(CompareTime(ret, LastWriteTime(StaticEnv::File))); file_time_type ret2 = last_write_time(StaticEnv::SymlinkToFile); - TEST_CHECK(ret == ret2); - TEST_CHECK(C::to_time_t(ret2) == LastWriteTime(StaticEnv::SymlinkToFile)); + TEST_CHECK(CompareTime(ret, ret2)); + TEST_CHECK(CompareTime(ret2, LastWriteTime(StaticEnv::SymlinkToFile))); } { file_time_type ret = last_write_time(StaticEnv::Dir); TEST_CHECK(ret != min); TEST_CHECK(ret < C::now()); - TEST_CHECK(C::to_time_t(ret) == LastWriteTime(StaticEnv::Dir)); + TEST_CHECK(CompareTime(ret, LastWriteTime(StaticEnv::Dir))); file_time_type ret2 = last_write_time(StaticEnv::SymlinkToDir); - TEST_CHECK(ret == ret2); - TEST_CHECK(C::to_time_t(ret2) == LastWriteTime(StaticEnv::SymlinkToDir)); + TEST_CHECK(CompareTime(ret, ret2)); + TEST_CHECK(CompareTime(ret2, LastWriteTime(StaticEnv::SymlinkToDir))); } } @@ -230,15 +366,17 @@ TEST_CASE(get_last_write_time_dynamic_env_test) const path dir = env.create_dir("dir"); const auto file_times = GetTimes(file); - const std::time_t file_write_time = file_times.write; + const TimeSpec file_write_time = file_times.write; const auto dir_times = GetTimes(dir); - const std::time_t dir_write_time = dir_times.write; + const TimeSpec dir_write_time = dir_times.write; file_time_type ftime = last_write_time(file); - TEST_CHECK(Clock::to_time_t(ftime) == file_write_time); + TEST_CHECK(Clock::to_time_t(ftime) == file_write_time.tv_sec); + TEST_CHECK(CompareTime(ftime, file_write_time)); file_time_type dtime = last_write_time(dir); - TEST_CHECK(Clock::to_time_t(dtime) == dir_write_time); + TEST_CHECK(Clock::to_time_t(dtime) == dir_write_time.tv_sec); + TEST_CHECK(CompareTime(dtime, dir_write_time)); SleepFor(Sec(2)); @@ -253,18 +391,15 @@ TEST_CASE(get_last_write_time_dynamic_env_test) TEST_CHECK(ftime2 > ftime); TEST_CHECK(dtime2 > dtime); - TEST_CHECK(LastWriteTime(file) == Clock::to_time_t(ftime2)); - TEST_CHECK(LastWriteTime(dir) == Clock::to_time_t(dtime2)); + TEST_CHECK(CompareTime(LastWriteTime(file), ftime2)); + TEST_CHECK(CompareTime(LastWriteTime(dir), dtime2)); } TEST_CASE(set_last_write_time_dynamic_env_test) { using Clock = file_time_type::clock; - using Sec = std::chrono::seconds; - using Hours = std::chrono::hours; - using Minutes = std::chrono::minutes; - using MicroSec = std::chrono::microseconds; + using SubSecT = file_time_type::duration; scoped_test_env env; const path file = env.create_file("file", 42); @@ -272,15 +407,17 @@ TEST_CASE(set_last_write_time_dynamic_env_test) const auto now = Clock::now(); const file_time_type epoch_time = now - now.time_since_epoch(); - const file_time_type future_time = now + Hours(3) + Sec(42) + MicroSec(17); - const file_time_type past_time = now - Minutes(3) - Sec(42) - MicroSec(17); - const file_time_type before_epoch_time = epoch_time - Minutes(3) - Sec(42) - MicroSec(17); + const file_time_type future_time = now + Hours(3) + Sec(42) + SubSec(17); + const file_time_type past_time = now - Minutes(3) - Sec(42) - SubSec(17); + const file_time_type before_epoch_time = + epoch_time - Minutes(3) - Sec(42) - SubSec(17); // FreeBSD has a bug in their utimes implementation where the time is not update // when the number of seconds is '-1'. #if defined(__FreeBSD__) - const file_time_type just_before_epoch_time = epoch_time - Sec(2) - MicroSec(17); + const file_time_type just_before_epoch_time = + epoch_time - Sec(2) - SubSec(17); #else - const file_time_type just_before_epoch_time = epoch_time - MicroSec(17); + const file_time_type just_before_epoch_time = epoch_time - SubSec(17); #endif struct TestCase { @@ -300,7 +437,8 @@ TEST_CASE(set_last_write_time_dynamic_env_test) }; for (const auto& TC : cases) { const auto old_times = GetTimes(TC.p); - file_time_type old_time(Sec(old_times.write)); + file_time_type old_time; + TEST_REQUIRE(ConvertFromTimeSpec(old_time, old_times.write)); std::error_code ec = GetTestEC(); last_write_time(TC.p, TC.new_time, ec); @@ -310,14 +448,8 @@ TEST_CASE(set_last_write_time_dynamic_env_test) if (TimeIsRepresentableByFilesystem(TC.new_time)) { TEST_CHECK(got_time != old_time); - if (TC.new_time < epoch_time) { - TEST_CHECK(got_time <= TC.new_time); - TEST_CHECK(got_time > TC.new_time - Sec(1)); - } else { - TEST_CHECK(got_time <= TC.new_time + Sec(1)); - TEST_CHECK(got_time >= TC.new_time - Sec(1)); - } - TEST_CHECK(LastAccessTime(TC.p) == old_times.access); + TEST_CHECK(CompareTime(got_time, TC.new_time)); + TEST_CHECK(CompareTime(LastAccessTime(TC.p), old_times.access)); } } } @@ -325,9 +457,6 @@ TEST_CASE(set_last_write_time_dynamic_env_test) TEST_CASE(last_write_time_symlink_test) { using Clock = file_time_type::clock; - using Sec = std::chrono::seconds; - using Hours = std::chrono::hours; - using Minutes = std::chrono::minutes; scoped_test_env env; @@ -343,77 +472,75 @@ TEST_CASE(last_write_time_symlink_test) last_write_time(sym, new_time, ec); TEST_CHECK(!ec); - const std::time_t new_time_t = Clock::to_time_t(new_time); file_time_type got_time = last_write_time(sym); - std::time_t got_time_t = Clock::to_time_t(got_time); - - TEST_CHECK(got_time_t != old_times.write); - TEST_CHECK(got_time_t == new_time_t); - TEST_CHECK(LastWriteTime(file) == new_time_t); - TEST_CHECK(LastAccessTime(sym) == old_times.access); - TEST_CHECK(GetSymlinkTimes(sym) == old_sym_times); + TEST_CHECK(!CompareTime(got_time, old_times.write)); + TEST_CHECK(got_time == new_time); + + TEST_CHECK(CompareTime(LastWriteTime(file), new_time)); + TEST_CHECK(CompareTime(LastAccessTime(sym), old_times.access)); + std::pair sym_times = GetSymlinkTimes(sym); + TEST_CHECK(CompareTime(sym_times.first, old_sym_times.first)); + TEST_CHECK(CompareTime(sym_times.second, old_sym_times.second)); } TEST_CASE(test_write_min_time) { using Clock = file_time_type::clock; - using Sec = std::chrono::seconds; - using MicroSec = std::chrono::microseconds; - using Lim = std::numeric_limits; scoped_test_env env; const path p = env.create_file("file", 42); - - std::error_code ec = GetTestEC(); + const file_time_type old_time = last_write_time(p); file_time_type new_time = file_time_type::min(); + std::error_code ec = GetTestEC(); last_write_time(p, new_time, ec); file_time_type tt = last_write_time(p); if (TimeIsRepresentableByFilesystem(new_time)) { TEST_CHECK(!ec); - TEST_CHECK(tt >= new_time); - TEST_CHECK(tt < new_time + Sec(1)); - - ec = GetTestEC(); - last_write_time(p, Clock::now()); + TEST_CHECK(CompareTime(tt, new_time)); - new_time = file_time_type::min() + MicroSec(1); + last_write_time(p, old_time); + new_time = file_time_type::min() + SubSec(1); + ec = GetTestEC(); last_write_time(p, new_time, ec); tt = last_write_time(p); if (TimeIsRepresentableByFilesystem(new_time)) { TEST_CHECK(!ec); - TEST_CHECK(tt >= new_time); - TEST_CHECK(tt < new_time + Sec(1)); + TEST_CHECK(CompareTime(tt, new_time)); + } else { + TEST_CHECK(ErrorIs(ec, std::errc::value_too_large)); + TEST_CHECK(tt == old_time); } + } else { + TEST_CHECK(ErrorIs(ec, std::errc::value_too_large)); + TEST_CHECK(tt == old_time); } } +TEST_CASE(test_write_max_time) { + using Clock = file_time_type::clock; + using Sec = std::chrono::seconds; + using Hours = std::chrono::hours; + scoped_test_env env; + const path p = env.create_file("file", 42); + const file_time_type old_time = last_write_time(p); + file_time_type new_time = file_time_type::max(); -TEST_CASE(test_write_min_max_time) -{ - using Clock = file_time_type::clock; - using Sec = std::chrono::seconds; - using Hours = std::chrono::hours; - using Lim = std::numeric_limits; - scoped_test_env env; - const path p = env.create_file("file", 42); - - std::error_code ec = GetTestEC(); - file_time_type new_time = file_time_type::max(); - - ec = GetTestEC(); - last_write_time(p, new_time, ec); - file_time_type tt = last_write_time(p); + std::error_code ec = GetTestEC(); + last_write_time(p, new_time, ec); + file_time_type tt = last_write_time(p); - if (TimeIsRepresentableByFilesystem(new_time)) { - TEST_CHECK(!ec); - TEST_CHECK(tt > new_time - Sec(1)); - TEST_CHECK(tt <= new_time); - } + if (TimeIsRepresentableByFilesystem(new_time)) { + TEST_CHECK(!ec); + TEST_CHECK(CompareTime(tt, new_time)); + } else { + TEST_CHECK(ErrorIs(ec, std::errc::value_too_large)); + TEST_CHECK(tt == old_time); + } } TEST_CASE(test_value_on_failure) @@ -421,8 +548,7 @@ TEST_CASE(test_value_on_failure) const path p = StaticEnv::DNE; std::error_code ec = GetTestEC(); TEST_CHECK(last_write_time(p, ec) == file_time_type::min()); - TEST_CHECK(ec); - TEST_CHECK(ec != GetTestEC()); + TEST_CHECK(ErrorIs(ec, std::errc::no_such_file_or_directory)); } TEST_CASE(test_exists_fails) @@ -434,10 +560,30 @@ TEST_CASE(test_exists_fails) std::error_code ec = GetTestEC(); TEST_CHECK(last_write_time(file, ec) == file_time_type::min()); - TEST_CHECK(ec); - TEST_CHECK(ec != GetTestEC()); + TEST_CHECK(ErrorIs(ec, std::errc::permission_denied)); + + ExceptionChecker Checker(file, std::errc::permission_denied, + "last_write_time"); + TEST_CHECK_THROW_RESULT(filesystem_error, Checker, last_write_time(file)); +} - TEST_CHECK_THROW(filesystem_error, last_write_time(file)); +TEST_CASE(my_test) { + scoped_test_env env; + const path p = env.create_file("file", 42); + using namespace std::chrono; + using TimeSpec = struct ::timespec; + TimeSpec ts[2]; + ts[0].tv_sec = 0; + ts[0].tv_nsec = UTIME_OMIT; + ts[1].tv_sec = -1; + ts[1].tv_nsec = + duration_cast(seconds(1) - nanoseconds(13)).count(); + if (::utimensat(AT_FDCWD, p.c_str(), ts, 0) == -1) { + TEST_CHECK(false); + } + TimeSpec new_ts = LastWriteTime(p); + TEST_CHECK(ts[1].tv_sec == new_ts.tv_sec); + TEST_CHECK(ts[1].tv_nsec == new_ts.tv_nsec); } TEST_SUITE_END() -- GitLab From 6ac92555a60828f1961eb3c2e0986874df94b047 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 21:01:45 +0000 Subject: [PATCH 084/495] Make compile with gcc 4.8.5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Victor Zverovich. This fixes an error when compiling `` with gcc 4.8.5: ``` .../libcxx/src/experimental/filesystem/filesystem_common.h:137:34: error: redeclaration ‘T std::experimental::filesystem::v1::detail::{anonymous}::error_value() [with T = bool]’ d iffers in ‘constexpr’ constexpr bool error_value() { ^ .../libcxx/src/experimental/filesystem/filesystem_common.h:133:3: error: from previous declaration ‘T std::experimental::filesystem::v1::detail::{anonymous}::error_value() [with T = bool]’ T error_value(); ^ ``` Reviewed as https://reviews.llvm.org/D49813 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337962 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/filesystem_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index 7be167460..43453a0ad 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -118,11 +118,11 @@ T error_value(); template <> _LIBCPP_CONSTEXPR_AFTER_CXX11 void error_value() {} template <> -constexpr bool error_value() { +bool error_value() { return false; } template <> -constexpr uintmax_t error_value() { +uintmax_t error_value() { return uintmax_t(-1); } template <> -- GitLab From 7450cbb7478cd5a9b1d49cadaae0a7480186e1d3 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Wed, 25 Jul 2018 21:50:44 +0000 Subject: [PATCH 085/495] [libc++] Follow-up to r337960: specify lambda's return type to avoid -Wc++11-narrowing warning on Darwin The internal CI produced the following diagnostic: error: non-constant-expression cannot be narrowed from type 'long long' to '__darwin_suseconds_t' (aka 'int') in initializer list [-Wc++11-narrowing] struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)}, ^~~~~~~~~~~~~~~~~~~~~~ git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337968 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/filesystem_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index 43453a0ad..d330b764b 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -393,7 +393,7 @@ bool set_file_times(const path& p, std::array const& TS, error_code& ec) { #if !defined(_LIBCPP_USE_UTIMENSAT) using namespace chrono; - auto Convert = [](long nsec) { + auto Convert = [](long nsec) -> decltype(std::declval<::timeval>().tv_usec) { return duration_cast(nanoseconds(nsec)).count(); }; struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)}, -- GitLab From d2992ce2fed0fa1cccfc01f61a508899d25b66a0 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 21:53:43 +0000 Subject: [PATCH 086/495] Fix failing test under C++14 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337970 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/filesystem_common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index d330b764b..5c18930ca 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -362,8 +362,8 @@ public: // The tv_nsec and tv_usec fields must not be negative so adjust accordingly if (subsec_dur.count() < 0) { if (sec_dur.count() > min_seconds) { - sec_dur -= fs_seconds(1); - subsec_dur += fs_seconds(1); + sec_dur = sec_dur - fs_seconds(1); + subsec_dur = subsec_dur + fs_seconds(1); } else { subsec_dur = fs_nanoseconds::zero(); } -- GitLab From 0c29afae930f9a2123a60932fd62be8f0ee7cfb5 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 21:58:37 +0000 Subject: [PATCH 087/495] Remove test which shouldn't have been committed git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337971 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../last_write_time.pass.cpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp index b216c5f17..8404900f5 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -567,23 +567,4 @@ TEST_CASE(test_exists_fails) TEST_CHECK_THROW_RESULT(filesystem_error, Checker, last_write_time(file)); } -TEST_CASE(my_test) { - scoped_test_env env; - const path p = env.create_file("file", 42); - using namespace std::chrono; - using TimeSpec = struct ::timespec; - TimeSpec ts[2]; - ts[0].tv_sec = 0; - ts[0].tv_nsec = UTIME_OMIT; - ts[1].tv_sec = -1; - ts[1].tv_nsec = - duration_cast(seconds(1) - nanoseconds(13)).count(); - if (::utimensat(AT_FDCWD, p.c_str(), ts, 0) == -1) { - TEST_CHECK(false); - } - TimeSpec new_ts = LastWriteTime(p); - TEST_CHECK(ts[1].tv_sec == new_ts.tv_sec); - TEST_CHECK(ts[1].tv_nsec == new_ts.tv_nsec); -} - TEST_SUITE_END() -- GitLab From 39ee0c622f3e02faa15d38cb9d256e02db75ea0e Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 22:07:36 +0000 Subject: [PATCH 088/495] Fix GCC build in C++14 w/o c++14 constexpr git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337974 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/filesystem_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index 5c18930ca..a74cae457 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -229,7 +229,7 @@ struct time_util_base { .count(); private: -#if _LIBCPP_STD_VER > 11 +#if _LIBCPP_STD_VER > 11 && !defined(_LIBCPP_HAS_NO_CXX14_CONSTEXPR) static constexpr fs_duration get_min_nsecs() { return duration_cast( fs_nanoseconds(min_nsec_timespec) - -- GitLab From 98e53227ebe340be25d33012008b18b5b6a80a0a Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Wed, 25 Jul 2018 22:21:47 +0000 Subject: [PATCH 089/495] Work around GCC bug in constexpr function git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337976 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../experimental/filesystem/convert_file_time.sh.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp b/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp index 4c18eedc6..918236641 100644 --- a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp +++ b/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp @@ -56,11 +56,12 @@ constexpr TestKind getFileTimeTestKind() { using Rep = typename FileTimeT::rep; if (std::is_floating_point::value) return TK_FloatingPoint; - if (sizeof(Rep) == 16) + else if (sizeof(Rep) == 16) return TK_128Bit; - if (sizeof(Rep) == 8) + else if (sizeof(Rep) == 8) return TK_64Bit; - assert(false && "test kind not supported"); + else + assert(false && "test kind not supported"); } template Date: Wed, 25 Jul 2018 22:57:39 +0000 Subject: [PATCH 090/495] [CMake] Don't install c++abi headers in standalone libc++ build This is a refinement on r337833. Previously we were installing two copies of c++abi headers in libc++ build directory, one in include/c++build and another one in include/c++/v1. However, the second copy is unnecessary when building libc++ standalone. Differential Revision: https://reviews.llvm.org/D49752 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337979 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 1 - cmake/Modules/HandleLibCXXABI.cmake | 2 +- include/CMakeLists.txt | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29357b088..1dd8725c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -407,7 +407,6 @@ elseif(LLVM_LIBRARY_OUTPUT_INTDIR) set(LIBCXX_HEADER_DIR ${LLVM_BINARY_DIR}) else() set(LIBCXX_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXX_LIBDIR_SUFFIX}) - set(LIBCXX_HEADER_DIR ${CMAKE_BINARY_DIR}) endif() file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}") diff --git a/cmake/Modules/HandleLibCXXABI.cmake b/cmake/Modules/HandleLibCXXABI.cmake index 54b1e1286..ef3b4f5dd 100644 --- a/cmake/Modules/HandleLibCXXABI.cmake +++ b/cmake/Modules/HandleLibCXXABI.cmake @@ -48,7 +48,7 @@ macro(setup_abi_lib abidefines abilib abifiles abidirs) COMMENT "Copying C++ ABI header ${fpath}...") list(APPEND abilib_headers "${dst}") - if (NOT LIBCXX_USING_INSTALLED_LLVM) + if (NOT LIBCXX_USING_INSTALLED_LLVM AND LIBCXX_HEADER_DIR) set(dst "${LIBCXX_HEADER_DIR}/include/c++/v1/${dstdir}/${fpath}") add_custom_command(OUTPUT ${dst} DEPENDS ${src} diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index c60e61e6d..f4f894154 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -205,7 +205,7 @@ else() ) endif() -if(NOT LIBCXX_USING_INSTALLED_LLVM AND LLVM_BINARY_DIR) +if(NOT LIBCXX_USING_INSTALLED_LLVM AND LIBCXX_HEADER_DIR) set(output_dir ${LIBCXX_HEADER_DIR}/include/c++/v1) set(out_files) -- GitLab From 104b331e4c280684adca12e42714c47abfba9b01 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Wed, 25 Jul 2018 23:59:54 +0000 Subject: [PATCH 091/495] [libc++] Follow-up to r337968: use an explicit cast as suggested by Eric git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337984 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/filesystem_common.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index a74cae457..5d2a5ed4e 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -393,8 +393,10 @@ bool set_file_times(const path& p, std::array const& TS, error_code& ec) { #if !defined(_LIBCPP_USE_UTIMENSAT) using namespace chrono; - auto Convert = [](long nsec) -> decltype(std::declval<::timeval>().tv_usec) { - return duration_cast(nanoseconds(nsec)).count(); + auto Convert = [](long nsec) { + using int_type = decltype(std::declval<::timeval>().tv_usec); + auto dur = duration_cast(nanoseconds(nsec)).count(); + return static_cast(dur); }; struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)}, {TS[1].tv_sec, Convert(TS[1].tv_nsec)}}; -- GitLab From 6b101f1be13e4b29b854a7a3bdd23783dc987898 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 26 Jul 2018 00:34:50 +0000 Subject: [PATCH 092/495] [libc++] Add hack to allow ubsan to work w/o compiler-rt (__muloti4 is undefined) Summary: Using int128_t with UBSAN causes link errors unless compiler-rt is providing the runtime library. Specifically ubsan generates calls to __muloti4 but libgcc doesn't provide a definition. In order to avoid this, and allow users to continue using sanitized versions of libc++, this patch introduces a hack. It adds a cribbed version of the compiler-rt builtin to the libc++ filesystem sources. I don't think this approach will work in the long run, but it seems OK for now. Also see: https://bugs.llvm.org/show_bug.cgi?id=30643 https://bugs.llvm.org/show_bug.cgi?id=16404 Reviewers: mclow.lists, ldionne, rsmith, jyknight, echristo Reviewed By: echristo Subscribers: dberris, cfe-commits Differential Revision: https://reviews.llvm.org/D49828 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337990 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../filesystem/int128_builtins.cpp | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/experimental/filesystem/int128_builtins.cpp diff --git a/src/experimental/filesystem/int128_builtins.cpp b/src/experimental/filesystem/int128_builtins.cpp new file mode 100644 index 000000000..b168bf525 --- /dev/null +++ b/src/experimental/filesystem/int128_builtins.cpp @@ -0,0 +1,55 @@ +/*===-- int128_builtins.cpp - Implement __muloti4 --------------------------=== + * + * 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. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __muloti4, and is stolen from the compiler_rt library. + * + * FIXME: we steal and re-compile it into filesystem, which uses __int128_t, + * and requires this builtin when sanitized. See llvm.org/PR30643 + * + * ===----------------------------------------------------------------------=== + */ +#include "__config" +#include "climits" + +#ifndef _LIBCPP_HAS_NO_INT128 + +__attribute__((no_sanitize("undefined"))) extern "C" __int128_t +__muloti4(__int128_t a, __int128_t b, int* overflow) { + const int N = (int)(sizeof(__int128_t) * CHAR_BIT); + const __int128_t MIN = (__int128_t)1 << (N - 1); + const __int128_t MAX = ~MIN; + *overflow = 0; + __int128_t result = a * b; + if (a == MIN) { + if (b != 0 && b != 1) + *overflow = 1; + return result; + } + if (b == MIN) { + if (a != 0 && a != 1) + *overflow = 1; + return result; + } + __int128_t sa = a >> (N - 1); + __int128_t abs_a = (a ^ sa) - sa; + __int128_t sb = b >> (N - 1); + __int128_t abs_b = (b ^ sb) - sb; + if (abs_a < 2 || abs_b < 2) + return result; + if (sa == sb) { + if (abs_a > MAX / abs_b) + *overflow = 1; + } else { + if (abs_a > MIN / -abs_b) + *overflow = 1; + } + return result; +} + +#endif -- GitLab From 8940394a74f318df71333001a206d011a4c9e1dc Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 26 Jul 2018 01:10:50 +0000 Subject: [PATCH 093/495] Add print statements to help debugging git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337991 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../last_write_time.pass.cpp | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp index 8404900f5..3443f9821 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -421,21 +421,23 @@ TEST_CASE(set_last_write_time_dynamic_env_test) #endif struct TestCase { + const char * case_name; path p; file_time_type new_time; } cases[] = { - {file, epoch_time}, - {dir, epoch_time}, - {file, future_time}, - {dir, future_time}, - {file, past_time}, - {dir, past_time}, - {file, before_epoch_time}, - {dir, before_epoch_time}, - {file, just_before_epoch_time}, - {dir, just_before_epoch_time} + {"file, epoch_time", file, epoch_time}, + {"dir, epoch_time", dir, epoch_time}, + {"file, future_time", file, future_time}, + {"dir, future_time", dir, future_time}, + {"file, past_time", file, past_time}, + {"dir, past_time", dir, past_time}, + {"file, before_epoch_time", file, before_epoch_time}, + {"dir, before_epoch_time", dir, before_epoch_time}, + {"file, just_before_epoch_time", file, just_before_epoch_time}, + {"dir, just_before_epoch_time", dir, just_before_epoch_time} }; for (const auto& TC : cases) { + std::cerr << "Test Case = " << TC.case_name << "\n"; const auto old_times = GetTimes(TC.p); file_time_type old_time; TEST_REQUIRE(ConvertFromTimeSpec(old_time, old_times.write)); @@ -444,11 +446,19 @@ TEST_CASE(set_last_write_time_dynamic_env_test) last_write_time(TC.p, TC.new_time, ec); TEST_CHECK(!ec); - file_time_type got_time = last_write_time(TC.p); + ec = GetTestEC(); + file_time_type got_time = last_write_time(TC.p, ec); + TEST_REQUIRE(!ec); if (TimeIsRepresentableByFilesystem(TC.new_time)) { TEST_CHECK(got_time != old_time); TEST_CHECK(CompareTime(got_time, TC.new_time)); + + // FIXME(EricWF): Remove these after getting information from + // some failing bots. + std::cerr << (long long)got_time.time_since_epoch().count() << std::endl; + std::cerr << (long long)TC.new_time.time_since_epoch().count() << std::endl; + TEST_CHECK(CompareTime(LastAccessTime(TC.p), old_times.access)); } } -- GitLab From 6655abbc335be16fe31f8f2527fe8a404ace6580 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 26 Jul 2018 03:28:48 +0000 Subject: [PATCH 094/495] Workaround OS X 10.11 behavior where stat truncates st_mtimespec to seconds. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337998 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../last_write_time.pass.cpp | 49 ++++++++++++++----- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp index 3443f9821..59f7d8133 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -225,6 +225,24 @@ static const bool SupportsNanosecondRoundTrip = [] { } }(); + +static const bool WorkaroundStatTruncatesToSeconds = [] { + MicroSec micros(3); + static_assert(std::is_same::value, ""); + + // Test for the behavior of OS X 10.11 and older, which truncates the result + // of st_mtimespec to seconds. + file_time_type ft(micros); + { + scoped_test_env env; + const path p = env.create_file("file", 42); + if (LastWriteTime(p).tv_nsec != 0) + return false; + last_write_time(p, ft); + return last_write_time(p) != ft && LastWriteTime(p).tv_nsec == 0; + } +}(); + static const bool SupportsMinRoundTrip = [] { TimeSpec ts = {}; if (!ConvertToTimeSpec(ts, file_time_type::min())) @@ -244,7 +262,8 @@ static bool CompareTime(TimeSpec t1, TimeSpec t2) { return false; auto diff = std::abs(t1.tv_nsec - t2.tv_nsec); - + if (WorkaroundStatTruncatesToSeconds) + return diff < duration_cast(Sec(1)).count(); return diff < duration_cast(MicroSec(1)).count(); } @@ -275,8 +294,9 @@ static bool CompareTime(file_time_type t1, file_time_type t2) { dur = t1 - t2; else dur = t2 - t1; - - return duration_cast(dur).count() < 1; + if (WorkaroundStatTruncatesToSeconds) + return duration_cast(dur).count() == 0; + return duration_cast(dur).count() == 0; } // Check if a time point is representable on a given filesystem. Check that: @@ -399,7 +419,6 @@ TEST_CASE(get_last_write_time_dynamic_env_test) TEST_CASE(set_last_write_time_dynamic_env_test) { using Clock = file_time_type::clock; - using SubSecT = file_time_type::duration; scoped_test_env env; const path file = env.create_file("file", 42); @@ -453,12 +472,6 @@ TEST_CASE(set_last_write_time_dynamic_env_test) if (TimeIsRepresentableByFilesystem(TC.new_time)) { TEST_CHECK(got_time != old_time); TEST_CHECK(CompareTime(got_time, TC.new_time)); - - // FIXME(EricWF): Remove these after getting information from - // some failing bots. - std::cerr << (long long)got_time.time_since_epoch().count() << std::endl; - std::cerr << (long long)TC.new_time.time_since_epoch().count() << std::endl; - TEST_CHECK(CompareTime(LastAccessTime(TC.p), old_times.access)); } } @@ -484,7 +497,11 @@ TEST_CASE(last_write_time_symlink_test) file_time_type got_time = last_write_time(sym); TEST_CHECK(!CompareTime(got_time, old_times.write)); - TEST_CHECK(got_time == new_time); + if (!WorkaroundStatTruncatesToSeconds) { + TEST_CHECK(got_time == new_time); + } else { + TEST_CHECK(CompareTime(got_time, new_time)); + } TEST_CHECK(CompareTime(LastWriteTime(file), new_time)); TEST_CHECK(CompareTime(LastAccessTime(sym), old_times.access)); @@ -577,4 +594,14 @@ TEST_CASE(test_exists_fails) TEST_CHECK_THROW_RESULT(filesystem_error, Checker, last_write_time(file)); } +// Just for sanity ensure that WorkaroundStatTruncatesToSeconds is only +// ever true on Apple platforms. +TEST_CASE(apple_truncates_to_seconds_check) { +#ifndef __APPLE__ + TEST_CHECK(!WorkaroundStatTruncatesToSeconds); +#else + TEST_CHECK(SupportsNanosecondRoundTrip != WorkaroundStatTruncatesToSeconds); +#endif +} + TEST_SUITE_END() -- GitLab From 94d2ed559a0a4912eed549e3b33e0138caf6559f Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 26 Jul 2018 03:36:37 +0000 Subject: [PATCH 095/495] Fix attribute placement WRT extern C git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@337999 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/int128_builtins.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/experimental/filesystem/int128_builtins.cpp b/src/experimental/filesystem/int128_builtins.cpp index b168bf525..d8f2abbf9 100644 --- a/src/experimental/filesystem/int128_builtins.cpp +++ b/src/experimental/filesystem/int128_builtins.cpp @@ -19,8 +19,8 @@ #ifndef _LIBCPP_HAS_NO_INT128 -__attribute__((no_sanitize("undefined"))) extern "C" __int128_t -__muloti4(__int128_t a, __int128_t b, int* overflow) { +extern "C" __attribute__((no_sanitize("undefined"))) +__int128_t __muloti4(__int128_t a, __int128_t b, int* overflow) { const int N = (int)(sizeof(__int128_t) * CHAR_BIT); const __int128_t MIN = (__int128_t)1 << (N - 1); const __int128_t MAX = ~MIN; -- GitLab From cff3d7b20271a256e87b84cb09193f12ec659efe Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 26 Jul 2018 03:42:25 +0000 Subject: [PATCH 096/495] Correct comment about stat truncating st_mtimespec to seconds git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338000 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../last_write_time.pass.cpp | 25 +++++-------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp index 59f7d8133..616264d3d 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ b/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -208,15 +208,11 @@ static const bool SupportsMinTime = [] { static const bool SupportsNanosecondRoundTrip = [] { NanoSec ns(3); - - // Test if the file_time_type period is less than that of nanoseconds. - auto ft_dur = duration_cast(ns); - if (duration_cast(ft_dur) != ns) - return false; + static_assert(std::is_same::value, ""); // Test that the system call we use to set the times also supports nanosecond // resolution. (utimes does not) - file_time_type ft(ft_dur); + file_time_type ft(ns); { scoped_test_env env; const path p = env.create_file("file", 42); @@ -225,13 +221,14 @@ static const bool SupportsNanosecondRoundTrip = [] { } }(); - +// The HFS+ filesystem (used by default before macOS 10.13) stores timestamps at +// a 1-second granularity, and APFS (now the default) at a 1 nanosecond granularity. +// 1-second granularity is also the norm on many of the supported filesystems +// on Linux as well. static const bool WorkaroundStatTruncatesToSeconds = [] { MicroSec micros(3); static_assert(std::is_same::value, ""); - // Test for the behavior of OS X 10.11 and older, which truncates the result - // of st_mtimespec to seconds. file_time_type ft(micros); { scoped_test_env env; @@ -594,14 +591,4 @@ TEST_CASE(test_exists_fails) TEST_CHECK_THROW_RESULT(filesystem_error, Checker, last_write_time(file)); } -// Just for sanity ensure that WorkaroundStatTruncatesToSeconds is only -// ever true on Apple platforms. -TEST_CASE(apple_truncates_to_seconds_check) { -#ifndef __APPLE__ - TEST_CHECK(!WorkaroundStatTruncatesToSeconds); -#else - TEST_CHECK(SupportsNanosecondRoundTrip != WorkaroundStatTruncatesToSeconds); -#endif -} - TEST_SUITE_END() -- GitLab From d1759cf0e989daeb2b93f62636519cda177d8498 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 26 Jul 2018 03:57:26 +0000 Subject: [PATCH 097/495] Cleanup the last_write_time internals git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338001 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../filesystem/filesystem_common.h | 40 +++++++++++-------- src/experimental/filesystem/operations.cpp | 3 +- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/experimental/filesystem/filesystem_common.h b/src/experimental/filesystem/filesystem_common.h index 5d2a5ed4e..94f4d41cc 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/experimental/filesystem/filesystem_common.h @@ -19,6 +19,7 @@ #include #include #include +#include // for ::utimes as used in __last_write_time #include /* values for fchmodat */ #include @@ -33,14 +34,6 @@ #endif #endif -#if !defined(_LIBCPP_USE_UTIMENSAT) -#include // for ::utimes as used in __last_write_time -#endif - -#if !defined(UTIME_OMIT) -#include // for ::utimes as used in __last_write_time -#endif - #if defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" @@ -389,9 +382,11 @@ TimeSpec extract_mtime(StatT const& st) { return st.st_mtim; } TimeSpec extract_atime(StatT const& st) { return st.st_atim; } #endif -bool set_file_times(const path& p, std::array const& TS, +// allow the utimes implementation to compile even it we're not going +// to use it. + +bool posix_utimes(const path& p, std::array const& TS, error_code& ec) { -#if !defined(_LIBCPP_USE_UTIMENSAT) using namespace chrono; auto Convert = [](long nsec) { using int_type = decltype(std::declval<::timeval>().tv_usec); @@ -400,22 +395,35 @@ bool set_file_times(const path& p, std::array const& TS, }; struct ::timeval ConvertedTS[2] = {{TS[0].tv_sec, Convert(TS[0].tv_nsec)}, {TS[1].tv_sec, Convert(TS[1].tv_nsec)}}; - if (::utimes(p.c_str(), ConvertedTS) == -1) -#else + if (::utimes(p.c_str(), ConvertedTS) == -1) { + ec = capture_errno(); + return true; + } + return false; +} + +#if defined(_LIBCPP_USE_UTIMENSAT) +bool posix_utimensat(const path& p, std::array const& TS, + error_code& ec) { if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) -#endif { ec = capture_errno(); return true; } return false; } +#endif -bool set_time_spec_to(TimeSpec& TS, file_time_type NewTime) { - return !fs_time::set_times_checked( - &TS.tv_sec, &TS.tv_nsec, NewTime); +bool set_file_times(const path& p, std::array const& TS, + error_code& ec) { +#if !defined(_LIBCPP_USE_UTIMENSAT) + return posix_utimes(p, TS, ec); +#else + return posix_utimensat(p, TS, ec); +#endif } + } // namespace } // end namespace detail diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index d57066875..028d5bf0b 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -1017,6 +1017,7 @@ file_time_type __last_write_time(const path& p, error_code *ec) void __last_write_time(const path& p, file_time_type new_time, error_code *ec) { + using detail::fs_time; ErrorHandler err("last_write_time", ec, &p); error_code m_ec; @@ -1034,7 +1035,7 @@ void __last_write_time(const path& p, file_time_type new_time, tbuf[0].tv_sec = 0; tbuf[0].tv_nsec = UTIME_OMIT; #endif - if (detail::set_time_spec_to(tbuf[1], new_time)) + if (!fs_time::convert_to_timespec(tbuf[1], new_time)) return err.report(errc::value_too_large); detail::set_file_times(p, tbuf, m_ec); -- GitLab From 8928a12b4ea6ceb4f119db5eee485fc84ab8424c Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 26 Jul 2018 04:02:06 +0000 Subject: [PATCH 098/495] Be more consistent about which bool value means an error occurred git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338002 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/experimental/filesystem/operations.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/experimental/filesystem/operations.cpp b/src/experimental/filesystem/operations.cpp index 028d5bf0b..775c178b3 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/experimental/filesystem/operations.cpp @@ -433,19 +433,19 @@ bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, error_code& ec) { if (::ftruncate(fd.fd, to_size) == -1) { ec = capture_errno(); - return false; + return true; } ec.clear(); - return true; + return false; } bool posix_fchmod(const FileDescriptor& fd, const StatT& st, error_code& ec) { if (::fchmod(fd.fd, st.st_mode) == -1) { ec = capture_errno(); - return false; + return true; } ec.clear(); - return true; + return false; } bool stat_equivalent(const StatT& st1, const StatT& st2) { @@ -796,9 +796,9 @@ bool __copy_file(const path& from, const path& to, copy_options options, return err.report(errc::bad_file_descriptor); // Set the permissions and truncate the file we opened. - if (!detail::posix_fchmod(to_fd, from_stat, m_ec)) + if (detail::posix_fchmod(to_fd, from_stat, m_ec)) return err.report(m_ec); - if (!detail::posix_ftruncate(to_fd, 0, m_ec)) + if (detail::posix_ftruncate(to_fd, 0, m_ec)) return err.report(m_ec); } -- GitLab From 14535e3ad68311c098303f9599a44686a5dea89e Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Thu, 26 Jul 2018 05:08:30 +0000 Subject: [PATCH 099/495] Copy LLVM CMake configuration for CMake Policy CMP0068 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338005 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dd8725c4..2bffb19ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,10 @@ endif() if(POLICY CMP0022) cmake_policy(SET CMP0022 NEW) # Required when interacting with LLVM and Clang endif() +if(POLICY CMP0068) + cmake_policy(SET CMP0068 NEW) + set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON) +endif() # Add path for custom modules set(CMAKE_MODULE_PATH -- GitLab From 47d2a98a330e8bae6f4c06363bfb9c25c2aa131b Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Thu, 26 Jul 2018 05:10:24 +0000 Subject: [PATCH 100/495] [CMake] Don't generate linker script only when shared library isn't statically linked Since r337668, we support statically linking dependencies only to shared or static library. However, that change hasn't updated the check whether to generate a linker script. We shouldn't generate linker script only in the case when we aren't statically linked ABI into the shared library. Differential Revision: https://reviews.llvm.org/D49834 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338006 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bffb19ac..0a692ac62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,7 +179,7 @@ cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY # is on. This option is also disabled when the ABI library is not specified # or is specified to be "none". set(ENABLE_LINKER_SCRIPT_DEFAULT_VALUE OFF) -if (LLVM_HAVE_LINK_VERSION_SCRIPT AND NOT LIBCXX_ENABLE_STATIC_ABI_LIBRARY +if (LLVM_HAVE_LINK_VERSION_SCRIPT AND NOT LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY AND NOT LIBCXX_CXX_ABI_LIBNAME STREQUAL "none" AND NOT LIBCXX_CXX_ABI_LIBNAME STREQUAL "default" AND PYTHONINTERP_FOUND @@ -374,7 +374,7 @@ if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT) endif() endif() -if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT) +if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT) message(FATAL_ERROR "Conflicting options given. LIBCXX_ENABLE_STATIC_ABI_LIBRARY cannot be specified with LIBCXX_ENABLE_ABI_LINKER_SCRIPT") -- GitLab From a0866c5fb5020d15c69deda94d32a7f982b88dc9 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 27 Jul 2018 03:07:09 +0000 Subject: [PATCH 101/495] Implement This patch implements the header and uses that to provide . Unlike other standard headers, the symbols needed for have not yet been placed in libc++.so. Instead they live in the new libc++fs.a library. Users of filesystem are required to link this library. (Also note that libc++experimental no longer contains the definition of , which now requires linking libc++fs). The reason for keeping out of the dylib for now is that it's still somewhat experimental, and the possibility of requiring an ABI breaking change is very real. In the future the symbols will likely be moved into the dylib, or the dylib will be made to link libc++fs automagically). Note that moving the symbols out of libc++experimental may break user builds until they update to -lc++fs. This should be OK, because the experimental library provides no stability guarantees. However, I plan on looking into ways we can force libc++experimental to automagically link libc++fs. In order to use a single implementation and set of tests for , it has been placed in a special `__fs` namespace. This namespace is inline in C++17 onward, but not before that. As such implementation is available in C++11 onward, but no filesystem namespace is present "directly", and as such name conflicts shouldn't occur in C++11 or C++14. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338093 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 4 + docs/BuildingLibcxx.rst | 10 +- docs/UsingLibcxx.rst | 21 + include/__config | 37 +- include/experimental/__config | 2 - include/experimental/filesystem | 2464 +-------------- include/filesystem | 2682 +++++++++++++++++ include/fstream | 61 + include/module.modulemap | 4 + lib/CMakeLists.txt | 50 +- .../filesystem/directory_iterator.cpp | 289 +- .../filesystem/filesystem_common.h | 25 +- .../filesystem/int128_builtins.cpp | 2 +- .../filesystem/operations.cpp | 685 ++--- test/libcxx/double_include.sh.cpp | 1 + .../experimental/filesystem/version.pass.cpp | 2 - .../last_write_time.sh.cpp | 4 +- .../class.path/path.itr/iterator_db.pass.cpp | 6 +- ...erse_iterator_produces_diagnostic.fail.cpp | 6 +- .../class.path/path.req/is_pathable.pass.cpp | 6 +- .../filesystems}/convert_file_time.sh.cpp | 8 +- .../filesystems}/lit.local.cfg | 0 .../input.output/filesystems/version.pass.cpp | 20 + .../filebuf.members/open_path.pass.cpp | 56 + .../fstreams/fstream.cons/path.pass.cpp | 49 + .../fstream.members/open_path.pass.cpp | 52 + .../fstreams/ifstream.cons/path.pass.cpp | 53 + .../ifstream.members/open_path.pass.cpp | 48 + .../fstreams/ofstream.cons/path.pass.cpp | 69 + .../ofstream.members/open_path.pass.cpp | 62 + .../Inputs/static_test_env/bad_symlink | 0 .../Inputs/static_test_env/dir1/dir2/afile3 | 0 .../static_test_env/dir1/dir2/dir3/file5 | 0 .../Inputs/static_test_env/dir1/dir2/file4 | 0 .../static_test_env/dir1/dir2/symlink_to_dir3 | 0 .../Inputs/static_test_env/dir1/file1 | 0 .../Inputs/static_test_env/dir1/file2 | 0 .../Inputs/static_test_env/empty_file | 0 .../Inputs/static_test_env/non_empty_file | 0 .../Inputs/static_test_env/symlink_to_dir | 0 .../static_test_env/symlink_to_empty_file | 0 .../directory_entry.cons/copy.pass.cpp | 2 +- .../directory_entry.cons/copy_assign.pass.cpp | 2 +- .../directory_entry.cons/default.pass.cpp | 2 +- .../default_const.pass.cpp | 2 +- .../directory_entry.cons/move.pass.cpp | 2 +- .../directory_entry.cons/move_assign.pass.cpp | 2 +- .../directory_entry.cons/path.pass.cpp | 2 +- .../directory_entry.mods/assign.pass.cpp | 2 +- .../directory_entry.mods/refresh.pass.cpp | 2 +- .../replace_filename.pass.cpp | 2 +- .../directory_entry.obs/comparisons.pass.cpp | 2 +- .../directory_entry.obs/file_size.pass.cpp | 2 +- .../file_type_obs.pass.cpp | 2 +- .../hard_link_count.pass.cpp | 2 +- .../last_write_time.pass.cpp | 2 +- .../directory_entry.obs/path.pass.cpp | 2 +- .../directory_entry.obs/status.pass.cpp | 2 +- .../symlink_status.pass.cpp | 2 +- .../directory_iterator.members/copy.pass.cpp | 2 +- .../copy_assign.pass.cpp | 2 +- .../directory_iterator.members/ctor.pass.cpp | 2 +- .../default_ctor.pass.cpp | 2 +- .../increment.pass.cpp | 2 +- .../directory_iterator.members/move.pass.cpp | 2 +- .../move_assign.pass.cpp | 2 +- .../begin_end.pass.cpp | 2 +- .../class.directory_iterator/types.pass.cpp | 2 +- .../file_status.cons.pass.cpp | 2 +- .../file_status.mods.pass.cpp | 2 +- .../file_status.obs.pass.cpp | 2 +- .../filesystem_error.members.pass.cpp | 2 +- .../class.path/path.itr/iterator.pass.cpp | 2 +- .../path.member/path.append.pass.cpp | 2 +- .../path.assign/braced_init.pass.cpp | 2 +- .../path.member/path.assign/copy.pass.cpp | 2 +- .../path.member/path.assign/move.pass.cpp | 2 +- .../path.member/path.assign/source.pass.cpp | 2 +- .../path.member/path.compare.pass.cpp | 2 +- .../path.member/path.concat.pass.cpp | 2 +- .../path.member/path.construct/copy.pass.cpp | 2 +- .../path.construct/default.pass.cpp | 2 +- .../path.member/path.construct/move.pass.cpp | 2 +- .../path.construct/source.pass.cpp | 2 +- .../path.member/path.decompose/empty.fail.cpp | 2 +- .../path.decompose/path.decompose.pass.cpp | 2 +- .../path.gen/lexically_normal.pass.cpp | 2 +- .../lexically_relative_and_proximate.pass.cpp | 2 +- .../generic_string_alloc.pass.cpp | 2 +- .../path.generic.obs/named_overloads.pass.cpp | 2 +- .../path.member/path.modifiers/clear.pass.cpp | 2 +- .../path.modifiers/make_preferred.pass.cpp | 2 +- .../path.modifiers/remove_filename.pass.cpp | 2 +- .../path.modifiers/replace_extension.pass.cpp | 2 +- .../path.modifiers/replace_filename.pass.cpp | 2 +- .../path.member/path.modifiers/swap.pass.cpp | 2 +- .../path.native.obs/c_str.pass.cpp | 2 +- .../path.native.obs/named_overloads.pass.cpp | 2 +- .../path.native.obs/native.pass.cpp | 2 +- .../path.native.obs/operator_string.pass.cpp | 2 +- .../path.native.obs/string_alloc.pass.cpp | 2 +- .../tested_in_path_decompose.pass.cpp | 2 +- .../path.nonmember/append_op.pass.cpp | 2 +- .../comparison_ops_tested_elsewhere.pass.cpp | 0 .../hash_value_tested_elswhere.pass.cpp | 0 .../path.nonmember/path.factory.pass.cpp | 2 +- .../path.nonmember/path.io.pass.cpp | 2 +- .../path.io.unicode_bug.pass.cpp | 2 +- .../class.path/path.nonmember/swap.pass.cpp | 2 +- .../filesystems}/class.path/synop.pass.cpp | 2 +- .../rec.dir.itr.members/copy.pass.cpp | 2 +- .../rec.dir.itr.members/copy_assign.pass.cpp | 2 +- .../rec.dir.itr.members/ctor.pass.cpp | 2 +- .../rec.dir.itr.members/depth.pass.cpp | 2 +- .../disable_recursion_pending.pass.cpp | 2 +- .../rec.dir.itr.members/increment.pass.cpp | 2 +- .../rec.dir.itr.members/move.pass.cpp | 2 +- .../rec.dir.itr.members/move_assign.pass.cpp | 2 +- .../rec.dir.itr.members/pop.pass.cpp | 2 +- .../recursion_pending.pass.cpp | 2 +- .../rec.dir.itr.nonmembers/begin_end.pass.cpp | 2 +- .../fs.enum/check_bitmask_types.hpp | 0 .../fs.enum/enum.copy_options.pass.cpp | 2 +- .../fs.enum/enum.directory_options.pass.cpp | 2 +- .../fs.enum/enum.file_type.pass.cpp | 2 +- .../fs.enum/enum.path.format.pass.cpp | 2 +- .../fs.enum/enum.perm_options.pass.cpp | 2 +- .../filesystems}/fs.enum/enum.perms.pass.cpp | 2 +- .../fs.error.report/tested_elsewhere.pass.cpp | 0 .../file_time_type.pass.cpp | 2 +- .../fs.op.absolute/absolute.pass.cpp | 2 +- .../fs.op.canonical/canonical.pass.cpp | 2 +- .../fs.op.funcs/fs.op.copy/copy.pass.cpp | 2 +- .../fs.op.copy_file/copy_file.pass.cpp | 2 +- .../fs.op.copy_file/copy_file_large.pass.cpp | 2 +- .../fs.op.copy_symlink/copy_symlink.pass.cpp | 2 +- .../create_directories.pass.cpp | 2 +- .../create_directory.pass.cpp | 2 +- .../create_directory_with_attributes.pass.cpp | 2 +- .../create_directory_symlink.pass.cpp | 2 +- .../create_hard_link.pass.cpp | 2 +- .../create_symlink.pass.cpp | 2 +- .../fs.op.current_path/current_path.pass.cpp | 2 +- .../fs.op.equivalent/equivalent.pass.cpp | 2 +- .../fs.op.funcs/fs.op.exists/exists.pass.cpp | 2 +- .../fs.op.file_size/file_size.pass.cpp | 2 +- .../fs.op.hard_lk_ct/hard_link_count.pass.cpp | 2 +- .../is_block_file.pass.cpp | 2 +- .../is_character_file.pass.cpp | 2 +- .../fs.op.is_directory/is_directory.pass.cpp | 2 +- .../fs.op.is_empty/is_empty.pass.cpp | 2 +- .../fs.op.is_fifo/is_fifo.pass.cpp | 2 +- .../fs.op.is_other/is_other.pass.cpp | 2 +- .../is_regular_file.pass.cpp | 2 +- .../fs.op.is_socket/is_socket.pass.cpp | 2 +- .../fs.op.is_symlink/is_symlink.pass.cpp | 2 +- .../last_write_time.pass.cpp | 2 +- .../fs.op.permissions/permissions.pass.cpp | 2 +- .../fs.op.proximate/proximate.pass.cpp | 2 +- .../fs.op.read_symlink/read_symlink.pass.cpp | 2 +- .../fs.op.relative/relative.pass.cpp | 2 +- .../fs.op.funcs/fs.op.remove/remove.pass.cpp | 2 +- .../fs.op.remove_all/remove_all.pass.cpp | 2 +- .../fs.op.funcs/fs.op.rename/rename.pass.cpp | 2 +- .../fs.op.resize_file/resize_file.pass.cpp | 2 +- .../fs.op.funcs/fs.op.space/space.pass.cpp | 2 +- .../fs.op.funcs/fs.op.status/status.pass.cpp | 2 +- .../fs.op.status_known/status_known.pass.cpp | 2 +- .../symlink_status.pass.cpp | 2 +- .../temp_directory_path.pass.cpp | 2 +- .../weakly_canonical.pass.cpp | 2 +- .../fs.req.macros/feature_macro.pass.cpp | 29 + .../fs.req.namespace/namespace.fail.cpp | 29 + .../fs.req.namespace/namespace.pass.cpp | 26 + .../filesystems}/lit.local.cfg | 0 test/support/filesystem_include.hpp | 15 +- utils/libcxx/test/config.py | 10 +- www/cxx1z_status.html | 4 +- 178 files changed, 3980 insertions(+), 3163 deletions(-) create mode 100644 include/filesystem rename src/{experimental => }/filesystem/directory_iterator.cpp (55%) rename src/{experimental => }/filesystem/filesystem_common.h (96%) rename src/{experimental => }/filesystem/int128_builtins.cpp (97%) rename src/{experimental => }/filesystem/operations.cpp (76%) rename test/libcxx/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp (96%) rename test/libcxx/{experimental/filesystem => input.output/filesystems}/class.path/path.itr/iterator_db.pass.cpp (93%) rename test/libcxx/{experimental/filesystem => input.output/filesystems}/class.path/path.itr/reverse_iterator_produces_diagnostic.fail.cpp (87%) rename test/libcxx/{experimental/filesystem => input.output/filesystems}/class.path/path.req/is_pathable.pass.cpp (96%) rename test/libcxx/{experimental/filesystem => input.output/filesystems}/convert_file_time.sh.cpp (98%) rename test/libcxx/{experimental/filesystem => input.output/filesystems}/lit.local.cfg (100%) create mode 100644 test/libcxx/input.output/filesystems/version.pass.cpp create mode 100644 test/std/input.output/file.streams/fstreams/filebuf.members/open_path.pass.cpp create mode 100644 test/std/input.output/file.streams/fstreams/fstream.cons/path.pass.cpp create mode 100644 test/std/input.output/file.streams/fstreams/fstream.members/open_path.pass.cpp create mode 100644 test/std/input.output/file.streams/fstreams/ifstream.cons/path.pass.cpp create mode 100644 test/std/input.output/file.streams/fstreams/ifstream.members/open_path.pass.cpp create mode 100644 test/std/input.output/file.streams/fstreams/ofstream.cons/path.pass.cpp create mode 100644 test/std/input.output/file.streams/fstreams/ofstream.members/open_path.pass.cpp rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/bad_symlink (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/dir1/dir2/afile3 (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/dir1/dir2/dir3/file5 (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/dir1/dir2/file4 (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/dir1/file1 (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/dir1/file2 (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/empty_file (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/non_empty_file (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/symlink_to_dir (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/Inputs/static_test_env/symlink_to_empty_file (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.cons/copy.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.cons/default.pass.cpp (96%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.cons/default_const.pass.cpp (96%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.cons/move.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.cons/move_assign.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.cons/path.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.mods/assign.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.mods/refresh.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.obs/comparisons.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.obs/file_size.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.obs/path.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.obs/status.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_iterator/directory_iterator.members/copy.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_iterator/directory_iterator.members/ctor.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_iterator/directory_iterator.members/default_ctor.pass.cpp (96%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_iterator/directory_iterator.members/increment.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_iterator/directory_iterator.members/move.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.directory_iterator/types.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.file_status/file_status.cons.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.file_status/file_status.mods.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.file_status/file_status.obs.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.filesystem_error/filesystem_error.members.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.itr/iterator.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.append.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.assign/braced_init.pass.cpp (95%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.assign/copy.pass.cpp (96%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.assign/move.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.assign/source.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.compare.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.concat.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.construct/copy.pass.cpp (96%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.construct/default.pass.cpp (95%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.construct/move.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.construct/source.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.decompose/empty.fail.cpp (96%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.decompose/path.decompose.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.gen/lexically_normal.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.generic.obs/named_overloads.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.modifiers/clear.pass.cpp (96%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.modifiers/make_preferred.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.modifiers/remove_filename.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.modifiers/replace_extension.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.modifiers/replace_filename.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.modifiers/swap.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.native.obs/c_str.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.native.obs/named_overloads.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.native.obs/native.pass.cpp (96%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.native.obs/operator_string.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.native.obs/string_alloc.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.member/path.query/tested_in_path_decompose.pass.cpp (96%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.nonmember/append_op.pass.cpp (96%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.nonmember/comparison_ops_tested_elsewhere.pass.cpp (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.nonmember/hash_value_tested_elswhere.pass.cpp (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.nonmember/path.factory.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.nonmember/path.io.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.nonmember/path.io.unicode_bug.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/path.nonmember/swap.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.path/synop.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.enum/check_bitmask_types.hpp (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.enum/enum.copy_options.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.enum/enum.directory_options.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.enum/enum.file_type.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.enum/enum.path.format.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.enum/enum.perm_options.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.enum/enum.perms.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.error.report/tested_elsewhere.pass.cpp (100%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.filesystem.synopsis/file_time_type.pass.cpp (97%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.absolute/absolute.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.canonical/canonical.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.copy/copy.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.current_path/current_path.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.exists/exists.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.file_size/file_size.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.is_other/is_other.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.permissions/permissions.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.proximate/proximate.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.relative/relative.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.remove/remove.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.rename/rename.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.space/space.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.status/status.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.status_known/status_known.pass.cpp (98%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp (99%) rename test/std/{experimental/filesystem => input.output/filesystems}/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp (98%) create mode 100644 test/std/input.output/filesystems/fs.req.macros/feature_macro.pass.cpp create mode 100644 test/std/input.output/filesystems/fs.req.namespace/namespace.fail.cpp create mode 100644 test/std/input.output/filesystems/fs.req.namespace/namespace.pass.cpp rename test/std/{experimental/filesystem => input.output/filesystems}/lit.local.cfg (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a692ac62..cd4786ec6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,10 @@ option(LIBCXX_INSTALL_SUPPORT_HEADERS "Install libc++ support headers." ON) cmake_dependent_option(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY "Install libc++experimental.a" ON "LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY;LIBCXX_INSTALL_LIBRARY" OFF) +cmake_dependent_option(LIBCXX_INSTALL_FILESYSTEM_LIBRARY + "Install libc++fs.a" ON + "LIBCXX_ENABLE_FILESYSTEM_LIBRARY;LIBCXX_INSTALL_LIBRARY" OFF) + if (FUCHSIA) set(DEFAULT_ABI_VERSION 2) else() diff --git a/docs/BuildingLibcxx.rst b/docs/BuildingLibcxx.rst index 3dae2f41c..d0b03c675 100644 --- a/docs/BuildingLibcxx.rst +++ b/docs/BuildingLibcxx.rst @@ -242,11 +242,15 @@ libc++experimental Specific Options .. option:: LIBCXX_ENABLE_FILESYSTEM:BOOL - **Default**: ``LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY`` + **Default**: ``ON`` + + Build filesystem as a standalone library libc++fs.a. + +.. option:: LIBCXX_INSTALL_FILESYSTEM_LIBRARY:BOOL - Build filesystem as part of libc++experimental.a. This allows filesystem - to be disabled without turning off the entire experimental library. + **Default**: ``LIBCXX_ENABLE_FILESYSTEM AND LIBCXX_INSTALL_LIBRARY`` + Install libc++fs.a alongside libc++. .. _ABI Library Specific Options: diff --git a/docs/UsingLibcxx.rst b/docs/UsingLibcxx.rst index f54234d6a..e10a27c59 100644 --- a/docs/UsingLibcxx.rst +++ b/docs/UsingLibcxx.rst @@ -49,6 +49,24 @@ An example of using ``LD_LIBRARY_PATH``: $ export LD_LIBRARY_PATH=/lib $ ./a.out # Searches for libc++ along LD_LIBRARY_PATH + +Using ```` and libc++fs +==================================== + +Libc++ provides the implementation of the filesystem library in a separate +library. Users of ```` and ```` are +required to link ``-lc++fs``. + +.. note:: + Prior to libc++ 7.0, users of ```` were required + to link libc++experimental. + +.. warning:: + The Filesystem library is still experimental in nature. As such normal + guarantees about ABI stability and backwards compatibility do not yet apply + to it. In the future, this restriction will be removed. + + Using libc++experimental and ```` ===================================================== @@ -65,6 +83,9 @@ installed. For information on building libc++experimental from source see :ref:`Building Libc++ ` and :ref:`libc++experimental CMake Options `. +Note that as of libc++ 7.0 using the ```` requires linking +libc++fs instead of libc++experimental. + Also see the `Experimental Library Implementation Status `__ page. diff --git a/include/__config b/include/__config index f659ba943..4b17fb5e7 100644 --- a/include/__config +++ b/include/__config @@ -43,6 +43,18 @@ # endif #endif +#ifndef _LIBCPP_STD_VER +# if __cplusplus <= 201103L +# define _LIBCPP_STD_VER 11 +# elif __cplusplus <= 201402L +# define _LIBCPP_STD_VER 14 +# elif __cplusplus <= 201703L +# define _LIBCPP_STD_VER 17 +# else +# define _LIBCPP_STD_VER 18 // current year, or date of c++2a ratification +# endif +#endif // _LIBCPP_STD_VER + #if defined(__ELF__) # define _LIBCPP_OBJECT_FORMAT_ELF 1 #elif defined(__MACH__) @@ -462,6 +474,19 @@ namespace std { } } +#if _LIBCPP_STD_VER >= 17 +#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ + _LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem { +#else +#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ + _LIBCPP_BEGIN_NAMESPACE_STD namespace __fs { namespace filesystem { +#endif + +#define _LIBCPP_END_NAMESPACE_FILESYSTEM \ + _LIBCPP_END_NAMESPACE_STD } } + +#define _VSTD_FS _VSTD::__fs::filesystem + #if !defined(_LIBCPP_HAS_NO_ASAN) && !__has_feature(address_sanitizer) #define _LIBCPP_HAS_NO_ASAN #endif @@ -959,18 +984,6 @@ template struct __static_assert_check {}; #define _LIBCPP_WCTYPE_IS_MASK #endif -#ifndef _LIBCPP_STD_VER -# if __cplusplus <= 201103L -# define _LIBCPP_STD_VER 11 -# elif __cplusplus <= 201402L -# define _LIBCPP_STD_VER 14 -# elif __cplusplus <= 201703L -# define _LIBCPP_STD_VER 17 -# else -# define _LIBCPP_STD_VER 18 // current year, or date of c++2a ratification -# endif -#endif // _LIBCPP_STD_VER - #if _LIBCPP_STD_VER > 11 # define _LIBCPP_DEPRECATED [[deprecated]] #else diff --git a/include/experimental/__config b/include/experimental/__config index 97c25438a..55ae31b8a 100644 --- a/include/experimental/__config +++ b/include/experimental/__config @@ -52,8 +52,6 @@ #define _VSTD_CORO _VSTD_EXPERIMENTAL::coroutines_v1 -#define _VSTD_FS ::std::experimental::filesystem::v1 - #define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD \ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace parallelism_v2 { diff --git a/include/experimental/filesystem b/include/experimental/filesystem index dbc03595d..28d8dcf4f 100644 --- a/include/experimental/filesystem +++ b/include/experimental/filesystem @@ -231,21 +231,7 @@ */ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // for quoted -#include - -#include <__debug> +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -260,2453 +246,7 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_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 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 __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 __secs; - return time_point(__secs(__t)); - } -}; - -typedef chrono::time_point<_FilesystemClock> file_time_type; - -struct _LIBCPP_TYPE_VIS space_info -{ - uintmax_t capacity; - uintmax_t free; - uintmax_t available; -}; - -enum class _LIBCPP_ENUM_VIS file_type : signed char -{ - none = 0, - not_found = -1, - regular = 1, - directory = 2, - symlink = 3, - block = 4, - character = 5, - fifo = 6, - socket = 7, - unknown = 8 -}; - -enum class _LIBCPP_ENUM_VIS perms : unsigned -{ - none = 0, - - owner_read = 0400, - owner_write = 0200, - owner_exec = 0100, - owner_all = 0700, - - group_read = 040, - group_write = 020, - group_exec = 010, - group_all = 070, - - others_read = 04, - others_write = 02, - others_exec = 01, - others_all = 07, - - all = 0777, - - set_uid = 04000, - set_gid = 02000, - sticky_bit = 01000, - mask = 07777, - unknown = 0xFFFF, -}; - -_LIBCPP_INLINE_VISIBILITY -inline constexpr perms operator&(perms _LHS, perms _RHS) -{ return static_cast(static_cast(_LHS) & static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr perms operator|(perms _LHS, perms _RHS) -{ return static_cast(static_cast(_LHS) | static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr perms operator^(perms _LHS, perms _RHS) -{ return static_cast(static_cast(_LHS) ^ static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr perms operator~(perms _LHS) -{ return static_cast(~static_cast(_LHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline perms& operator&=(perms& _LHS, perms _RHS) -{ return _LHS = _LHS & _RHS; } - -_LIBCPP_INLINE_VISIBILITY -inline perms& operator|=(perms& _LHS, perms _RHS) -{ return _LHS = _LHS | _RHS; } - -_LIBCPP_INLINE_VISIBILITY -inline perms& operator^=(perms& _LHS, perms _RHS) -{ return _LHS = _LHS ^ _RHS; } - -enum class _LIBCPP_ENUM_VIS perm_options : unsigned char { - replace = 1, - add = 2, - remove = 4, - nofollow = 8 -}; - -_LIBCPP_INLINE_VISIBILITY -inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) -{ return static_cast(static_cast(_LHS) & static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) -{ return static_cast(static_cast(_LHS) | static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) -{ return static_cast(static_cast(_LHS) ^ static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr perm_options operator~(perm_options _LHS) -{ return static_cast(~static_cast(_LHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) -{ return _LHS = _LHS & _RHS; } - -_LIBCPP_INLINE_VISIBILITY -inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) -{ return _LHS = _LHS | _RHS; } - -_LIBCPP_INLINE_VISIBILITY -inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) -{ return _LHS = _LHS ^ _RHS; } - -enum class _LIBCPP_ENUM_VIS copy_options : unsigned short -{ - none = 0, - skip_existing = 1, - overwrite_existing = 2, - update_existing = 4, - recursive = 8, - copy_symlinks = 16, - skip_symlinks = 32, - directories_only = 64, - create_symlinks = 128, - create_hard_links = 256, - __in_recursive_copy = 512, -}; - -_LIBCPP_INLINE_VISIBILITY -inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) -{ return static_cast(static_cast(_LHS) & static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) -{ return static_cast(static_cast(_LHS) | static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) -{ return static_cast(static_cast(_LHS) ^ static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr copy_options operator~(copy_options _LHS) -{ return static_cast(~static_cast(_LHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) -{ return _LHS = _LHS & _RHS; } - -_LIBCPP_INLINE_VISIBILITY -inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) -{ return _LHS = _LHS | _RHS; } - -_LIBCPP_INLINE_VISIBILITY -inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) -{ return _LHS = _LHS ^ _RHS; } - - -enum class _LIBCPP_ENUM_VIS directory_options : unsigned char -{ - none = 0, - follow_directory_symlink = 1, - skip_permission_denied = 2 -}; - -_LIBCPP_INLINE_VISIBILITY -inline constexpr directory_options operator&(directory_options _LHS, directory_options _RHS) -{ return static_cast(static_cast(_LHS) & static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr directory_options operator|(directory_options _LHS, directory_options _RHS) -{ return static_cast(static_cast(_LHS) | static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr directory_options operator^(directory_options _LHS, directory_options _RHS) -{ return static_cast(static_cast(_LHS) ^ static_cast(_RHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline constexpr directory_options operator~(directory_options _LHS) -{ return static_cast(~static_cast(_LHS)); } - -_LIBCPP_INLINE_VISIBILITY -inline directory_options& operator&=(directory_options& _LHS, directory_options _RHS) -{ return _LHS = _LHS & _RHS; } - -_LIBCPP_INLINE_VISIBILITY -inline directory_options& operator|=(directory_options& _LHS, directory_options _RHS) -{ return _LHS = _LHS | _RHS; } - -_LIBCPP_INLINE_VISIBILITY -inline directory_options& operator^=(directory_options& _LHS, directory_options _RHS) -{ return _LHS = _LHS ^ _RHS; } - - -class _LIBCPP_TYPE_VIS file_status -{ -public: - // constructors - _LIBCPP_INLINE_VISIBILITY - file_status() noexcept : file_status(file_type::none) {} - _LIBCPP_INLINE_VISIBILITY - explicit file_status(file_type __ft, - perms __prms = perms::unknown) noexcept - : __ft_(__ft), __prms_(__prms) - {} - - file_status(const file_status&) noexcept = default; - file_status(file_status&&) noexcept = default; - - _LIBCPP_INLINE_VISIBILITY - ~file_status() {} - - file_status& operator=(const file_status&) noexcept = default; - file_status& operator=(file_status&&) noexcept = default; - - // observers - _LIBCPP_INLINE_VISIBILITY - file_type type() const noexcept { - return __ft_; - } - - _LIBCPP_INLINE_VISIBILITY - perms permissions() const noexcept { - return __prms_; - } - - // modifiers - _LIBCPP_INLINE_VISIBILITY - void type(file_type __ft) noexcept { - __ft_ = __ft; - } - - _LIBCPP_INLINE_VISIBILITY - void permissions(perms __p) noexcept { - __prms_ = __p; - } -private: - file_type __ft_; - perms __prms_; -}; - -class _LIBCPP_TYPE_VIS directory_entry; - -template struct __can_convert_char { - static const bool value = false; -}; -template struct __can_convert_char - : public __can_convert_char<_Tp> { -}; -template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char; -}; -template <> struct __can_convert_char { - static const bool value = true; - using __char_type = wchar_t; -}; -template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char16_t; -}; -template <> struct __can_convert_char { - static const bool value = true; - using __char_type = char32_t; -}; - -template -typename enable_if<__can_convert_char<_ECharT>::value, bool>::type -__is_separator(_ECharT __e) { - return __e == _ECharT('/'); -}; - -struct _NullSentinal {}; - -template -using _Void = void; - -template -struct __is_pathable_string : public false_type {}; - -template -struct __is_pathable_string, - _Void::__char_type>> -: public __can_convert_char<_ECharT> -{ - using _Str = basic_string<_ECharT, _Traits, _Alloc>; - using _Base = __can_convert_char<_ECharT>; - static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } - static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); } - static _ECharT __first_or_null(_Str const& __s) { - return __s.empty() ? _ECharT{} : __s[0]; - } -}; - - -template -struct __is_pathable_string, - _Void::__char_type>> -: public __can_convert_char<_ECharT> -{ - using _Str = basic_string_view<_ECharT, _Traits>; - using _Base = __can_convert_char<_ECharT>; - static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } - static _ECharT const* __range_end(_Str const& __s) { return __s.data() + __s.length(); } - static _ECharT __first_or_null(_Str const& __s) { - return __s.empty() ? _ECharT{} : __s[0]; - } -}; - -template ::type, - class _UnqualPtrType = typename remove_const< - typename remove_pointer<_DS>::type>::type, - bool _IsCharPtr = is_pointer<_DS>::value && - __can_convert_char<_UnqualPtrType>::value - > -struct __is_pathable_char_array : false_type {}; - -template -struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> - : __can_convert_char::type> -{ - using _Base = __can_convert_char::type>; - - static _ECharT const* __range_begin(const _ECharT* __b) { return __b; } - static _ECharT const* __range_end(const _ECharT* __b) - { - using _Iter = const _ECharT*; - const _ECharT __sentinal = _ECharT{}; - _Iter __e = __b; - for (; *__e != __sentinal; ++__e) - ; - return __e; - } - - static _ECharT __first_or_null(const _ECharT* __b) { return *__b; } -}; - -template ::value, class = void> -struct __is_pathable_iter : false_type {}; - -template -struct __is_pathable_iter<_Iter, true, - _Void::value_type>::__char_type>> - : __can_convert_char::value_type> -{ - using _ECharT = typename iterator_traits<_Iter>::value_type; - using _Base = __can_convert_char<_ECharT>; - - static _Iter __range_begin(_Iter __b) { return __b; } - static _NullSentinal __range_end(_Iter) { return _NullSentinal{}; } - - static _ECharT __first_or_null(_Iter __b) { return *__b; } -}; - -template ::value, - bool _IsCharIterT = __is_pathable_char_array<_Tp>::value, - bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value - > -struct __is_pathable : false_type { - static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false"); -}; - -template -struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {}; - - -template -struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> {}; - - -template -struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {}; - - -template -struct _PathCVT { - static_assert(__can_convert_char<_ECharT>::value, "Char type not convertible"); - - typedef __narrow_to_utf8 _Narrower; - - static void __append_range(string& __dest, _ECharT const* __b, _ECharT const* __e) { - _Narrower()(back_inserter(__dest), __b, __e); - } - - template - static void __append_range(string& __dest, _Iter __b, _Iter __e) { - static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload"); - if (__b == __e) return; - basic_string<_ECharT> __tmp(__b, __e); - _Narrower()(back_inserter(__dest), __tmp.data(), - __tmp.data() + __tmp.length()); - } - - template - static void __append_range(string& __dest, _Iter __b, _NullSentinal) { - static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload"); - const _ECharT __sentinal = _ECharT{}; - if (*__b == __sentinal) return; - basic_string<_ECharT> __tmp; - for (; *__b != __sentinal; ++__b) - __tmp.push_back(*__b); - _Narrower()(back_inserter(__dest), __tmp.data(), - __tmp.data() + __tmp.length()); - } - - template - static void __append_source(string& __dest, _Source const& __s) - { - using _Traits = __is_pathable<_Source>; - __append_range(__dest, _Traits::__range_begin(__s), _Traits::__range_end(__s)); - } -}; - -template <> -struct _PathCVT { - - template - static typename enable_if< - __is_exactly_input_iterator<_Iter>::value - >::type __append_range(string& __dest, _Iter __b, _Iter __e) { - for (; __b != __e; ++__b) - __dest.push_back(*__b); - } - - template - static typename enable_if< - __is_forward_iterator<_Iter>::value - >::type __append_range(string& __dest, _Iter __b, _Iter __e) { - __dest.__append_forward_unsafe(__b, __e); - } - - template - static void __append_range(string& __dest, _Iter __b, _NullSentinal) { - const char __sentinal = char{}; - for (; *__b != __sentinal; ++__b) - __dest.push_back(*__b); - } - - template - static void __append_source(string& __dest, _Source const& __s) - { - using _Traits = __is_pathable<_Source>; - __append_range(__dest, _Traits::__range_begin(__s), - _Traits::__range_end(__s)); - } -}; - - -class _LIBCPP_TYPE_VIS path -{ - template - using _EnableIfPathable = typename - enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type; - - template - using _SourceChar = typename __is_pathable<_Tp>::__char_type; - - template - using _SourceCVT = _PathCVT<_SourceChar<_Tp>>; - -public: - typedef char value_type; - typedef basic_string string_type; - typedef _VSTD::string_view __string_view; - static constexpr value_type preferred_separator = '/'; - - enum class _LIBCPP_ENUM_VIS format : unsigned char { - auto_format, - native_format, - generic_format - }; - - // constructors and destructor - _LIBCPP_INLINE_VISIBILITY path() noexcept {} - _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {} - _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept : __pn_(_VSTD::move(__p.__pn_)) {} - - _LIBCPP_INLINE_VISIBILITY - path(string_type&& __s, format = format::auto_format) noexcept - : __pn_(_VSTD::move(__s)) {} - - template < - class _Source, - class = _EnableIfPathable<_Source, void> - > - path(const _Source& __src, format = format::auto_format) { - _SourceCVT<_Source>::__append_source(__pn_, __src); - } - - template - path(_InputIt __first, _InputIt __last, format = format::auto_format) { - typedef typename iterator_traits<_InputIt>::value_type _ItVal; - _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); - } - - // TODO Implement locale conversions. - template - > - path(const _Source& __src, const locale& __loc, - format = format::auto_format); - template - path(_InputIt __first, _InputIt _last, const locale& __loc, - format = format::auto_format); - - _LIBCPP_INLINE_VISIBILITY - ~path() = default; - - // assignments - _LIBCPP_INLINE_VISIBILITY - path& operator=(const path& __p) { - __pn_ = __p.__pn_; - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - path& operator=(path&& __p) noexcept { - __pn_ = _VSTD::move(__p.__pn_); - return *this; - } - - template - _LIBCPP_INLINE_VISIBILITY - path& operator=(string_type&& __s) noexcept { - __pn_ = _VSTD::move(__s); - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - path& assign(string_type&& __s) noexcept { - __pn_ = _VSTD::move(__s); - return *this; - } - - template - _LIBCPP_INLINE_VISIBILITY - _EnableIfPathable<_Source> - operator=(const _Source& __src) - { return this->assign(__src); } - - - template - _EnableIfPathable<_Source> - assign(const _Source& __src) { - __pn_.clear(); - _SourceCVT<_Source>::__append_source(__pn_, __src); - return *this; - } - - template - path& assign(_InputIt __first, _InputIt __last) { - typedef typename iterator_traits<_InputIt>::value_type _ItVal; - __pn_.clear(); - _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); - return *this; - } - -private: - template - static bool __source_is_absolute(_ECharT __first_or_null) { - return __is_separator(__first_or_null); - } - -public: - // appends - path& operator/=(const path& __p) { - if (__p.is_absolute()) { - __pn_ = __p.__pn_; - return *this; - } - if (has_filename()) - __pn_ += preferred_separator; - __pn_ += __p.native(); - return *this; - } - - // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src - // is known at compile time to be "/' since the user almost certainly intended - // to append a separator instead of overwriting the path with "/" - template - _LIBCPP_INLINE_VISIBILITY - _EnableIfPathable<_Source> - operator/=(const _Source& __src) { - return this->append(__src); - } - - template - _EnableIfPathable<_Source> - append(const _Source& __src) { - using _Traits = __is_pathable<_Source>; - using _CVT = _PathCVT<_SourceChar<_Source>>; - if (__source_is_absolute(_Traits::__first_or_null(__src))) - __pn_.clear(); - else if (has_filename()) - __pn_ += preferred_separator; - _CVT::__append_source(__pn_, __src); - return *this; - } - - template - path& append(_InputIt __first, _InputIt __last) { - typedef typename iterator_traits<_InputIt>::value_type _ItVal; - static_assert(__can_convert_char<_ItVal>::value, "Must convertible"); - using _CVT = _PathCVT<_ItVal>; - if (__first != __last && __source_is_absolute(*__first)) - __pn_.clear(); - else if (has_filename()) - __pn_ += preferred_separator; - _CVT::__append_range(__pn_, __first, __last); - return *this; - } - - // concatenation - _LIBCPP_INLINE_VISIBILITY - path& operator+=(const path& __x) { - __pn_ += __x.__pn_; - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - path& operator+=(const string_type& __x) { - __pn_ += __x; - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - path& operator+=(__string_view __x) { - __pn_ += __x; - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - path& operator+=(const value_type* __x) { - __pn_ += __x; - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - path& operator+=(value_type __x) { - __pn_ += __x; - return *this; - } - - template - typename enable_if<__can_convert_char<_ECharT>::value, path&>::type - operator+=(_ECharT __x) - { - basic_string<_ECharT> __tmp; - __tmp += __x; - _PathCVT<_ECharT>::__append_source(__pn_, __tmp); - return *this; - } - - template - _EnableIfPathable<_Source> - operator+=(const _Source& __x) { - return this->concat(__x); - } - - template - _EnableIfPathable<_Source> - concat(const _Source& __x) { - _SourceCVT<_Source>::__append_source(__pn_, __x); - return *this; - } - - template - path& concat(_InputIt __first, _InputIt __last) { - typedef typename iterator_traits<_InputIt>::value_type _ItVal; - _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); - return *this; - } - - // modifiers - _LIBCPP_INLINE_VISIBILITY - void clear() noexcept { - __pn_.clear(); - } - - path& make_preferred() { return *this; } - - _LIBCPP_INLINE_VISIBILITY - path& remove_filename() { - auto __fname = __filename(); - if (!__fname.empty()) - __pn_.erase(__fname.data() - __pn_.data()); - return *this; - } - - path& replace_filename(const path& __replacement) { - remove_filename(); - return (*this /= __replacement); - } - - path& replace_extension(const path& __replacement = path()); - - _LIBCPP_INLINE_VISIBILITY - void swap(path& __rhs) noexcept { - __pn_.swap(__rhs.__pn_); - } - - // private helper to allow reserving memory in the path - _LIBCPP_INLINE_VISIBILITY - void __reserve(size_t __s) { __pn_.reserve(__s); } - - // native format observers - _LIBCPP_INLINE_VISIBILITY - const string_type& native() const noexcept { - return __pn_; - } - - _LIBCPP_INLINE_VISIBILITY - const value_type* c_str() const noexcept { return __pn_.c_str(); } - - _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; } - - template , - class _Allocator = allocator<_ECharT> > - basic_string<_ECharT, _Traits, _Allocator> - string(const _Allocator& __a = _Allocator()) const { - using _CVT = __widen_from_utf8; - using _Str = basic_string<_ECharT, _Traits, _Allocator>; - _Str __s(__a); - __s.reserve(__pn_.size()); - _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size()); - return __s; - } - - _LIBCPP_INLINE_VISIBILITY std::string string() const { return __pn_; } - _LIBCPP_INLINE_VISIBILITY std::wstring wstring() const { return string(); } - _LIBCPP_INLINE_VISIBILITY std::string u8string() const { return __pn_; } - _LIBCPP_INLINE_VISIBILITY std::u16string u16string() const { return string(); } - _LIBCPP_INLINE_VISIBILITY std::u32string u32string() const { return string(); } - - // generic format observers - template , - class _Allocator = allocator<_ECharT> - > - basic_string<_ECharT, _Traits, _Allocator> - generic_string(const _Allocator& __a = _Allocator()) const { - return string<_ECharT, _Traits, _Allocator>(__a); - } - - std::string generic_string() const { return __pn_; } - std::wstring generic_wstring() const { return string(); } - std::string generic_u8string() const { return __pn_; } - std::u16string generic_u16string() const { return string(); } - std::u32string generic_u32string() const { return string(); } - -private: - int __compare(__string_view) const; - __string_view __root_name() const; - __string_view __root_directory() const; - __string_view __root_path_raw() const; - __string_view __relative_path() const; - __string_view __parent_path() const; - __string_view __filename() const; - __string_view __stem() const; - __string_view __extension() const; - -public: - // compare - _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept { return __compare(__p.__pn_);} - _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const { return __compare(__s); } - _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const { return __compare(__s); } - _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const { return __compare(__s); } - - // decomposition - _LIBCPP_INLINE_VISIBILITY path root_name() const { return string_type(__root_name()); } - _LIBCPP_INLINE_VISIBILITY path root_directory() const { return string_type(__root_directory()); } - _LIBCPP_INLINE_VISIBILITY path root_path() const { return root_name().append(string_type(__root_directory())); } - _LIBCPP_INLINE_VISIBILITY path relative_path() const { return string_type(__relative_path()); } - _LIBCPP_INLINE_VISIBILITY path parent_path() const { return string_type(__parent_path()); } - _LIBCPP_INLINE_VISIBILITY path filename() const { return string_type(__filename()); } - _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem());} - _LIBCPP_INLINE_VISIBILITY path extension() const { return string_type(__extension()); } - - // query - _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY - bool empty() const noexcept { return __pn_.empty(); } - - _LIBCPP_INLINE_VISIBILITY bool has_root_name() const { return !__root_name().empty(); } - _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const { return !__root_directory().empty(); } - _LIBCPP_INLINE_VISIBILITY bool has_root_path() const { return !__root_path_raw().empty(); } - _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const { return !__relative_path().empty(); } - _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const { return !__parent_path().empty(); } - _LIBCPP_INLINE_VISIBILITY bool has_filename() const { return !__filename().empty(); } - _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); } - _LIBCPP_INLINE_VISIBILITY bool has_extension() const { return !__extension().empty(); } - - _LIBCPP_INLINE_VISIBILITY bool is_absolute() const { return has_root_directory(); } - _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); } - - // relative paths - path lexically_normal() const; - path lexically_relative(const path& __base) const; - - _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const { - path __result = this->lexically_relative(__base); - if (__result.native().empty()) - return *this; - return __result; - } - - // iterators - class _LIBCPP_TYPE_VIS iterator; - typedef iterator const_iterator; - - iterator begin() const; - iterator end() const; - - - template - _LIBCPP_INLINE_VISIBILITY - friend typename enable_if::value && - is_same<_Traits, char_traits>::value, - basic_ostream<_CharT, _Traits>& - >::type - operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) { - __os << std::__quoted(__p.native()); - return __os; - } - - template - _LIBCPP_INLINE_VISIBILITY - friend typename enable_if::value || - !is_same<_Traits, char_traits>::value, - basic_ostream<_CharT, _Traits>& - >::type - operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) { - __os << std::__quoted(__p.string<_CharT, _Traits>()); - return __os; - } - - template - _LIBCPP_INLINE_VISIBILITY - friend basic_istream<_CharT, _Traits>& - operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) - { - basic_string<_CharT, _Traits> __tmp; - __is >> __quoted(__tmp); - __p = __tmp; - return __is; - } - -private: - inline _LIBCPP_INLINE_VISIBILITY - path& __assign_view(__string_view const& __s) noexcept { __pn_ = string_type(__s); return *this; } - string_type __pn_; -}; - -inline _LIBCPP_INLINE_VISIBILITY -void swap(path& __lhs, path& __rhs) noexcept { - __lhs.swap(__rhs); -} - -_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 -_LIBCPP_INLINE_VISIBILITY -typename enable_if<__is_pathable<_Source>::value, path>::type -u8path(const _Source& __s){ - static_assert(is_same::__char_type, char>::value, - "u8path(Source const&) requires Source have a character type of type 'char'"); - return path(__s); -} - -template -_LIBCPP_INLINE_VISIBILITY -typename enable_if<__is_pathable<_InputIt>::value, path>::type -u8path(_InputIt __f, _InputIt __l) { - static_assert(is_same::__char_type, char>::value, - "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"); - return path(__f, __l); -} - -class _LIBCPP_TYPE_VIS path::iterator -{ -public: - enum _ParserState : unsigned char { - _Singular, - _BeforeBegin, - _InRootName, - _InRootDir, - _InFilenames, - _InTrailingSep, - _AtEnd - }; - -public: - typedef bidirectional_iterator_tag iterator_category; - - typedef path value_type; - typedef std::ptrdiff_t difference_type; - typedef const path* pointer; - typedef const path& reference; - - typedef void __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator - -public: - _LIBCPP_INLINE_VISIBILITY - iterator() : __stashed_elem_(), __path_ptr_(nullptr), - __entry_(), __state_(_Singular) {} - - iterator(const iterator&) = default; - ~iterator() = default; - - iterator& operator=(const iterator&) = default; - - _LIBCPP_INLINE_VISIBILITY - reference operator*() const { - return __stashed_elem_; - } - - _LIBCPP_INLINE_VISIBILITY - pointer operator->() const { - return &__stashed_elem_; - } - - _LIBCPP_INLINE_VISIBILITY - iterator& operator++() { - _LIBCPP_ASSERT(__state_ != _Singular, - "attempting to increment a singular iterator"); - _LIBCPP_ASSERT(__state_ != _AtEnd, - "attempting to increment the end iterator"); - return __increment(); - } - - _LIBCPP_INLINE_VISIBILITY - iterator operator++(int) { - iterator __it(*this); - this->operator++(); - return __it; - } - - _LIBCPP_INLINE_VISIBILITY - iterator& operator--() { - _LIBCPP_ASSERT(__state_ != _Singular, - "attempting to decrement a singular iterator"); - _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(), - "attempting to decrement the begin iterator"); - return __decrement(); - } - - _LIBCPP_INLINE_VISIBILITY - iterator operator--(int) { - iterator __it(*this); - this->operator--(); - return __it; - } - -private: - friend class path; - - inline _LIBCPP_INLINE_VISIBILITY - friend bool operator==(const iterator&, const iterator&); - - iterator& __increment(); - iterator& __decrement(); - - path __stashed_elem_; - const path* __path_ptr_; - path::__string_view __entry_; - _ParserState __state_; -}; - -inline _LIBCPP_INLINE_VISIBILITY -bool operator==(const path::iterator& __lhs, const path::iterator& __rhs) { - return __lhs.__path_ptr_ == __rhs.__path_ptr_ && - __lhs.__entry_.data() == __rhs.__entry_.data(); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool operator!=(const path::iterator& __lhs, const path::iterator& __rhs) { - return !(__lhs == __rhs); -} - -class _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error -{ -public: - _LIBCPP_INLINE_VISIBILITY - filesystem_error(const string& __what, error_code __ec) - : system_error(__ec, __what), - __storage_(make_shared<_Storage>(path(), path())) { - __create_what(0); - } - - _LIBCPP_INLINE_VISIBILITY - filesystem_error(const string& __what, const path& __p1, error_code __ec) - : system_error(__ec, __what), - __storage_(make_shared<_Storage>(__p1, path())) { - __create_what(1); - } - - _LIBCPP_INLINE_VISIBILITY - filesystem_error(const string& __what, const path& __p1, const path& __p2, - error_code __ec) - : system_error(__ec, __what), - __storage_(make_shared<_Storage>(__p1, __p2)) { - __create_what(2); - } - - _LIBCPP_INLINE_VISIBILITY - const path& path1() const noexcept { return __storage_->__p1_; } - - _LIBCPP_INLINE_VISIBILITY - const path& path2() const noexcept { return __storage_->__p2_; } - - ~filesystem_error() override; // key function - - _LIBCPP_INLINE_VISIBILITY - const char* what() const noexcept override { - return __storage_->__what_.c_str(); - } - - _LIBCPP_FUNC_VIS - void __create_what(int __num_paths); - - private: - struct _Storage { - _LIBCPP_INLINE_VISIBILITY - _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {} - - path __p1_; - path __p2_; - string __what_; - }; - shared_ptr<_Storage> __storage_; -}; - -template -_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY -#ifndef _LIBCPP_NO_EXCEPTIONS -void __throw_filesystem_error(_Args && ...__args) -{ - throw filesystem_error(std::forward<_Args>(__args)...); -} -#else -void __throw_filesystem_error(_Args&&...) -{ - _VSTD::abort(); -} -#endif - -// operational functions - -_LIBCPP_FUNC_VIS -path __absolute(const path&, error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -path __canonical(const path&, error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -void __copy(const path& __from, const path& __to, copy_options __opt, - error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -bool __copy_file(const path& __from, const path& __to, copy_options __opt, - error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -void __copy_symlink(const path& __existing_symlink, const path& __new_symlink, - error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -bool __create_directories(const path& p, error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -bool __create_directory(const path& p, error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -bool __create_directory(const path& p, const path & attributes, - error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -void __create_directory_symlink(const path& __to, const path& __new_symlink, - error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -void __create_hard_link(const path& __to, const path& __new_hard_link, - error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -void __create_symlink(const path& __to, const path& __new_symlink, - error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -path __current_path(error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -void __current_path(const path&, error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -bool __equivalent(const path&, const path&, error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -uintmax_t __file_size(const path&, error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -uintmax_t __hard_link_count(const path&, error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -bool __fs_is_empty(const path& p, error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -file_time_type __last_write_time(const path& p, error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -void __last_write_time(const path& p, file_time_type new_time, - error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -void __permissions(const path&, perms, perm_options, error_code* = nullptr); -_LIBCPP_FUNC_VIS -path __read_symlink(const path& p, error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -bool __remove(const path& p, error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -uintmax_t __remove_all(const path& p, error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -void __rename(const path& from, const path& to, error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -void __resize_file(const path& p, uintmax_t size, error_code *ec=nullptr); -_LIBCPP_FUNC_VIS -space_info __space(const path&, error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -file_status __status(const path&, error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -file_status __symlink_status(const path&, error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -path __system_complete(const path&, error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -path __temp_directory_path(error_code *__ec=nullptr); -_LIBCPP_FUNC_VIS -path __weakly_canonical(path const& __p, error_code *__ec=nullptr); - -inline _LIBCPP_INLINE_VISIBILITY -path current_path() { - return __current_path(); -} - -inline _LIBCPP_INLINE_VISIBILITY -path current_path(error_code& __ec) { - return __current_path(&__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void current_path(const path& __p) { - __current_path(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -void current_path(const path& __p, error_code& __ec) noexcept { - __current_path(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -path absolute(const path& __p) { - return __absolute(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -path absolute(const path& __p, error_code &__ec) { - return __absolute(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -path canonical(const path& __p) { - return __canonical(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -path canonical(const path& __p, error_code& __ec) { - return __canonical(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void copy(const path& __from, const path& __to) { - __copy(__from, __to, copy_options::none); -} - -inline _LIBCPP_INLINE_VISIBILITY -void copy(const path& __from, const path& __to, error_code& __ec) { - __copy(__from, __to, copy_options::none, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void copy(const path& __from, const path& __to, copy_options __opt) { - __copy(__from, __to, __opt); -} - -inline _LIBCPP_INLINE_VISIBILITY -void copy(const path& __from, const path& __to, - copy_options __opt, error_code& __ec) { - __copy(__from, __to, __opt, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool copy_file(const path& __from, const path& __to) { - return __copy_file(__from, __to, copy_options::none); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool copy_file(const path& __from, const path& __to, error_code& __ec) { - return __copy_file(__from, __to, copy_options::none, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool copy_file(const path& __from, const path& __to, copy_options __opt) { - return __copy_file(__from, __to, __opt); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool copy_file(const path& __from, const path& __to, - copy_options __opt, error_code& __ec){ - return __copy_file(__from, __to, __opt, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void copy_symlink(const path& __existing, const path& __new) { - __copy_symlink(__existing, __new); -} - -inline _LIBCPP_INLINE_VISIBILITY -void copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept { - __copy_symlink(__ext, __new, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool create_directories(const path& __p) { - return __create_directories(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool create_directories(const path& __p, error_code& __ec) { - return __create_directories(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool create_directory(const path& __p) { - return __create_directory(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool create_directory(const path& __p, error_code& __ec) noexcept { - return __create_directory(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool create_directory(const path& __p, const path& __attrs) { - return __create_directory(__p, __attrs); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool create_directory(const path& __p, const path& __attrs, error_code& __ec) noexcept { - return __create_directory(__p, __attrs, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void create_directory_symlink(const path& __to, const path& __new) { - __create_directory_symlink(__to, __new); -} - -inline _LIBCPP_INLINE_VISIBILITY -void create_directory_symlink(const path& __to, const path& __new, - error_code& __ec) noexcept { - __create_directory_symlink(__to, __new, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void create_hard_link(const path& __to, const path& __new) { - __create_hard_link(__to, __new); -} - -inline _LIBCPP_INLINE_VISIBILITY -void create_hard_link(const path& __to, const path& __new, error_code& __ec) noexcept { - __create_hard_link(__to, __new, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void create_symlink(const path& __to, const path& __new) { - __create_symlink(__to, __new); -} - -inline _LIBCPP_INLINE_VISIBILITY -void create_symlink(const path& __to, const path& __new, - error_code& __ec) noexcept { - return __create_symlink(__to, __new, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool status_known(file_status __s) noexcept { - return __s.type() != file_type::none; -} - -inline _LIBCPP_INLINE_VISIBILITY -bool exists(file_status __s) noexcept { - return status_known(__s) && __s.type() != file_type::not_found; -} - -inline _LIBCPP_INLINE_VISIBILITY -bool exists(const path& __p) { - return exists(__status(__p)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool exists(const path& __p, error_code& __ec) noexcept { - auto __s = __status(__p, &__ec); - if (status_known(__s)) __ec.clear(); - return exists(__s); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool equivalent(const path& __p1, const path& __p2) { - return __equivalent(__p1, __p2); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept { - return __equivalent(__p1, __p2, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -uintmax_t file_size(const path& __p) { - return __file_size(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -uintmax_t file_size(const path& __p, error_code& __ec) noexcept { - return __file_size(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -uintmax_t hard_link_count(const path& __p) { - return __hard_link_count(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -uintmax_t hard_link_count(const path& __p, error_code& __ec) noexcept { - return __hard_link_count(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_block_file(file_status __s) noexcept { - return __s.type() == file_type::block; -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_block_file(const path& __p) { - return is_block_file(__status(__p)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_block_file(const path& __p, error_code& __ec) noexcept { - return is_block_file(__status(__p, &__ec)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_character_file(file_status __s) noexcept { - return __s.type() == file_type::character; -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_character_file(const path& __p) { - return is_character_file(__status(__p)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_character_file(const path& __p, error_code& __ec) noexcept { - return is_character_file(__status(__p, &__ec)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_directory(file_status __s) noexcept { - return __s.type() == file_type::directory; -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_directory(const path& __p) { - return is_directory(__status(__p)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_directory(const path& __p, error_code& __ec) noexcept { - return is_directory(__status(__p, &__ec)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_empty(const path& __p) { - return __fs_is_empty(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_empty(const path& __p, error_code& __ec) { - return __fs_is_empty(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_fifo(file_status __s) noexcept { - return __s.type() == file_type::fifo; -} -inline _LIBCPP_INLINE_VISIBILITY -bool is_fifo(const path& __p) { - return is_fifo(__status(__p)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_fifo(const path& __p, error_code& __ec) noexcept { - return is_fifo(__status(__p, &__ec)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_regular_file(file_status __s) noexcept { - return __s.type() == file_type::regular; -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_regular_file(const path& __p) { - return is_regular_file(__status(__p)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_regular_file(const path& __p, error_code& __ec) noexcept { - return is_regular_file(__status(__p, &__ec)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_socket(file_status __s) noexcept { - return __s.type() == file_type::socket; -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_socket(const path& __p) { - return is_socket(__status(__p)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_socket(const path& __p, error_code& __ec) noexcept { - return is_socket(__status(__p, &__ec)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_symlink(file_status __s) noexcept { - return __s.type() == file_type::symlink; -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_symlink(const path& __p) { - return is_symlink(__symlink_status(__p)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_symlink(const path& __p, error_code& __ec) noexcept { - return is_symlink(__symlink_status(__p, &__ec)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_other(file_status __s) noexcept { - return exists(__s) - && !is_regular_file(__s) && !is_directory(__s) && !is_symlink(__s); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_other(const path& __p) { - return is_other(__status(__p)); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool is_other(const path& __p, error_code& __ec) noexcept { - return is_other(__status(__p, &__ec)); -} - -inline _LIBCPP_INLINE_VISIBILITY -file_time_type last_write_time(const path& __p) { - return __last_write_time(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -file_time_type last_write_time(const path& __p, error_code& __ec) noexcept { - return __last_write_time(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void last_write_time(const path& __p, file_time_type __t) { - __last_write_time(__p, __t); -} - -inline _LIBCPP_INLINE_VISIBILITY -void last_write_time(const path& __p, file_time_type __t, error_code& __ec) noexcept { - __last_write_time(__p, __t, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void permissions(const path& __p, perms __prms, - perm_options __opts = perm_options::replace) { - __permissions(__p, __prms, __opts); -} - -inline _LIBCPP_INLINE_VISIBILITY -void permissions(const path& __p, perms __prms, error_code& __ec) noexcept { - __permissions(__p, __prms, perm_options::replace, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void permissions(const path& __p, perms __prms, perm_options __opts, - error_code& __ec) { - __permissions(__p, __prms, __opts, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -path proximate(const path& __p, const path& __base, error_code& __ec) { - path __tmp = __weakly_canonical(__p, &__ec); - if (__ec) - return {}; - path __tmp_base = __weakly_canonical(__base, &__ec); - if (__ec) - return {}; - return __tmp.lexically_proximate(__tmp_base); -} - -inline _LIBCPP_INLINE_VISIBILITY -path proximate(const path& __p, error_code& __ec) { - return proximate(__p, current_path(), __ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -path proximate(const path& __p, const path& __base = current_path()) { - return __weakly_canonical(__p).lexically_proximate(__weakly_canonical(__base)); -} - -inline _LIBCPP_INLINE_VISIBILITY -path read_symlink(const path& __p) { - return __read_symlink(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -path read_symlink(const path& __p, error_code& __ec) { - return __read_symlink(__p, &__ec); -} - - -inline _LIBCPP_INLINE_VISIBILITY -path relative(const path& __p, const path& __base, error_code& __ec) { - path __tmp = __weakly_canonical(__p, &__ec); - if (__ec) - return path(); - path __tmpbase = __weakly_canonical(__base, &__ec); - if (__ec) - return path(); - return __tmp.lexically_relative(__tmpbase); -} - -inline _LIBCPP_INLINE_VISIBILITY -path relative(const path& __p, error_code& __ec) { - return relative(__p, current_path(), __ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -path relative(const path& __p, const path& __base=current_path()) { - return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base)); -} - - -inline _LIBCPP_INLINE_VISIBILITY -bool remove(const path& __p) { - return __remove(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -bool remove(const path& __p, error_code& __ec) noexcept { - return __remove(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -uintmax_t remove_all(const path& __p) { - return __remove_all(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -uintmax_t remove_all(const path& __p, error_code& __ec) { - return __remove_all(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void rename(const path& __from, const path& __to) { - return __rename(__from, __to); -} - -inline _LIBCPP_INLINE_VISIBILITY -void rename(const path& __from, const path& __to, error_code& __ec) noexcept { - return __rename(__from, __to, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -void resize_file(const path& __p, uintmax_t __ns) { - return __resize_file(__p, __ns); -} - -inline _LIBCPP_INLINE_VISIBILITY -void resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept { - return __resize_file(__p, __ns, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -space_info space(const path& __p) { - return __space(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -space_info space(const path& __p, error_code& __ec) noexcept { - return __space(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -file_status status(const path& __p) { - return __status(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -file_status status(const path& __p, error_code& __ec) noexcept { - return __status(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -file_status symlink_status(const path& __p) { - return __symlink_status(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -file_status symlink_status(const path& __p, error_code& __ec) noexcept { - return __symlink_status(__p, &__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -path temp_directory_path() { - return __temp_directory_path(); -} - -inline _LIBCPP_INLINE_VISIBILITY -path temp_directory_path(error_code& __ec) { - return __temp_directory_path(&__ec); -} - -inline _LIBCPP_INLINE_VISIBILITY -path weakly_canonical(path const& __p) { - return __weakly_canonical(__p); -} - -inline _LIBCPP_INLINE_VISIBILITY -path weakly_canonical(path const& __p, error_code& __ec) { - return __weakly_canonical(__p, &__ec); -} - - -class directory_iterator; -class recursive_directory_iterator; -class __dir_stream; - -class directory_entry -{ - typedef _VSTD_FS::path _Path; - -public: - // constructors and destructors - directory_entry() noexcept = default; - directory_entry(directory_entry const&) = default; - directory_entry(directory_entry&&) noexcept = default; - - _LIBCPP_INLINE_VISIBILITY - explicit directory_entry(_Path const& __p) : __p_(__p) { - error_code __ec; - __refresh(&__ec); - } - - _LIBCPP_INLINE_VISIBILITY - directory_entry(_Path const& __p, error_code &__ec) : __p_(__p) { - __refresh(&__ec); - } - - ~directory_entry() {} - - directory_entry& operator=(directory_entry const&) = default; - directory_entry& operator=(directory_entry&&) noexcept = default; - - _LIBCPP_INLINE_VISIBILITY - void assign(_Path const& __p) { - __p_ = __p; - error_code __ec; - __refresh(&__ec); - } - - _LIBCPP_INLINE_VISIBILITY - void assign(_Path const& __p, error_code& __ec) { - __p_ = __p; - __refresh(&__ec); - } - - _LIBCPP_INLINE_VISIBILITY - void replace_filename(_Path const& __p) { - __p_.replace_filename(__p); - error_code __ec; - __refresh(&__ec); - } - - _LIBCPP_INLINE_VISIBILITY - void replace_filename(_Path const& __p, error_code &__ec) { - __p_ = __p_.parent_path() / __p; - __refresh(&__ec); - } - - _LIBCPP_INLINE_VISIBILITY - void refresh() { - __refresh(); - } - - _LIBCPP_INLINE_VISIBILITY - void refresh(error_code& __ec) noexcept { __refresh(&__ec); } - - _LIBCPP_INLINE_VISIBILITY - _Path const& path() const noexcept { - return __p_; - } - - _LIBCPP_INLINE_VISIBILITY - operator const _Path&() const noexcept { - return __p_; - } - - _LIBCPP_INLINE_VISIBILITY - bool exists() const { - return _VSTD_FS::exists(file_status{__get_ft()}); - } - - _LIBCPP_INLINE_VISIBILITY - bool exists(error_code& __ec) const noexcept { - return _VSTD_FS::exists(file_status{__get_ft(&__ec)}); - } - - _LIBCPP_INLINE_VISIBILITY - bool is_block_file() const { - return __get_ft() == file_type::block; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_block_file(error_code& __ec) const noexcept { - return __get_ft(&__ec) == file_type::block; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_character_file() const { - return __get_ft() == file_type::character; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_character_file(error_code& __ec) const noexcept { - return __get_ft(&__ec) == file_type::character; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_directory() const { - return __get_ft() == file_type::directory; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_directory(error_code& __ec) const noexcept { - return __get_ft(&__ec) == file_type::directory; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_fifo() const { - return __get_ft() == file_type::fifo; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_fifo(error_code& __ec) const noexcept { - return __get_ft(&__ec) == file_type::fifo; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_other() const { - return _VSTD_FS::is_other(file_status{__get_ft()}); - } - - _LIBCPP_INLINE_VISIBILITY - bool is_other(error_code& __ec) const noexcept { - return _VSTD_FS::is_other(file_status{__get_ft(&__ec)}); - } - - _LIBCPP_INLINE_VISIBILITY - bool is_regular_file() const { - return __get_ft() == file_type::regular; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_regular_file(error_code& __ec) const noexcept { - return __get_ft(&__ec) == file_type::regular; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_socket() const { - return __get_ft() == file_type::socket; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_socket(error_code& __ec) const noexcept { - return __get_ft(&__ec) == file_type::socket; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_symlink() const { - return __get_sym_ft() == file_type::symlink; - } - - _LIBCPP_INLINE_VISIBILITY - bool is_symlink(error_code& __ec) const noexcept { - return __get_sym_ft(&__ec) == file_type::symlink; - } - _LIBCPP_INLINE_VISIBILITY - uintmax_t file_size() const { - return __get_size(); - } - - _LIBCPP_INLINE_VISIBILITY - uintmax_t file_size(error_code& __ec) const noexcept { - return __get_size(&__ec); - } - - _LIBCPP_INLINE_VISIBILITY - uintmax_t hard_link_count() const { - return __get_nlink(); - } - - _LIBCPP_INLINE_VISIBILITY - uintmax_t hard_link_count(error_code& __ec) const noexcept { - return __get_nlink(&__ec); - } - - _LIBCPP_INLINE_VISIBILITY - file_time_type last_write_time() const { - return __get_write_time(); - } - - _LIBCPP_INLINE_VISIBILITY - file_time_type last_write_time(error_code& __ec) const noexcept { - return __get_write_time(&__ec); - } - - _LIBCPP_INLINE_VISIBILITY - file_status status() const { - return __get_status(); - } - - _LIBCPP_INLINE_VISIBILITY - file_status status(error_code& __ec) const noexcept { - return __get_status(&__ec); - } - - _LIBCPP_INLINE_VISIBILITY - file_status symlink_status() const { - return __get_symlink_status(); - } - - _LIBCPP_INLINE_VISIBILITY - file_status symlink_status(error_code& __ec) const noexcept { - return __get_symlink_status(&__ec); - } - - _LIBCPP_INLINE_VISIBILITY - bool operator< (directory_entry const& __rhs) const noexcept { - return __p_ < __rhs.__p_; - } - - _LIBCPP_INLINE_VISIBILITY - bool operator==(directory_entry const& __rhs) const noexcept { - return __p_ == __rhs.__p_; - } - - _LIBCPP_INLINE_VISIBILITY - bool operator!=(directory_entry const& __rhs) const noexcept { - return __p_ != __rhs.__p_; - } - - _LIBCPP_INLINE_VISIBILITY - bool operator<=(directory_entry const& __rhs) const noexcept { - return __p_ <= __rhs.__p_; - } - - _LIBCPP_INLINE_VISIBILITY - bool operator> (directory_entry const& __rhs) const noexcept { - return __p_ > __rhs.__p_; - } - - _LIBCPP_INLINE_VISIBILITY - bool operator>=(directory_entry const& __rhs) const noexcept { - return __p_ >= __rhs.__p_; - } - -private: - friend class directory_iterator; - friend class recursive_directory_iterator; - friend class __dir_stream; - - enum _CacheType : unsigned char { - _Empty, - _IterSymlink, - _IterNonSymlink, - _RefreshSymlink, - _RefreshSymlinkUnresolved, - _RefreshNonSymlink - }; - - struct __cached_data { - uintmax_t __size_; - uintmax_t __nlink_; - file_time_type __write_time_; - perms __sym_perms_; - perms __non_sym_perms_; - file_type __type_; - _CacheType __cache_type_; - - _LIBCPP_INLINE_VISIBILITY - __cached_data() noexcept { __reset(); } - - _LIBCPP_INLINE_VISIBILITY - void __reset() { - __cache_type_ = _Empty; - __type_ = file_type::none; - __sym_perms_ = __non_sym_perms_ = perms::unknown; - __size_ = __nlink_ = uintmax_t(-1); - __write_time_ = file_time_type::min(); - } - }; - - _LIBCPP_INLINE_VISIBILITY - static __cached_data __create_iter_result(file_type __ft) { - __cached_data __data; - __data.__type_ = __ft; - __data.__cache_type_ = [&]() { - switch (__ft) { - case file_type::none: - return _Empty; - case file_type::symlink: - return _IterSymlink; - default: - return _IterNonSymlink; - } - }(); - return __data; - } - - _LIBCPP_INLINE_VISIBILITY - void __assign_iter_entry(_Path&& __p, __cached_data __dt) { - __p_ = std::move(__p); - __data_ = __dt; - } - - _LIBCPP_FUNC_VIS - error_code __do_refresh() noexcept; - - _LIBCPP_INLINE_VISIBILITY - static bool __is_dne_error(error_code const& __ec) { - if (!__ec) - return true; - switch (static_cast(__ec.value())) { - case errc::no_such_file_or_directory: - case errc::not_a_directory: - return true; - default: - return false; - } - } - - _LIBCPP_INLINE_VISIBILITY - void __handle_error(const char* __msg, error_code* __dest_ec, - error_code const& __ec, - bool __allow_dne = false) const { - if (__dest_ec) { - *__dest_ec = __ec; - return; - } - if (__ec && (!__allow_dne || !__is_dne_error(__ec))) - __throw_filesystem_error(__msg, __p_, __ec); - } - - _LIBCPP_INLINE_VISIBILITY - void __refresh(error_code* __ec = nullptr) { - __handle_error("in directory_entry::refresh", __ec, __do_refresh(), - /*allow_dne*/ true); - } - - _LIBCPP_INLINE_VISIBILITY - file_type __get_sym_ft(error_code *__ec = nullptr) const { - switch (__data_.__cache_type_) { - case _Empty: - return __symlink_status(__p_, __ec).type(); - case _IterSymlink: - case _RefreshSymlink: - case _RefreshSymlinkUnresolved: - if (__ec) - __ec->clear(); - return file_type::symlink; - case _IterNonSymlink: - case _RefreshNonSymlink: - file_status __st(__data_.__type_); - if (__ec && !_VSTD_FS::exists(__st)) - *__ec = make_error_code(errc::no_such_file_or_directory); - else if (__ec) - __ec->clear(); - return __data_.__type_; - } - _LIBCPP_UNREACHABLE(); - } - - _LIBCPP_INLINE_VISIBILITY - file_type __get_ft(error_code *__ec = nullptr) const { - switch (__data_.__cache_type_) { - case _Empty: - case _IterSymlink: - case _RefreshSymlinkUnresolved: - return __status(__p_, __ec).type(); - case _IterNonSymlink: - case _RefreshNonSymlink: - case _RefreshSymlink: { - file_status __st(__data_.__type_); - if (__ec && !_VSTD_FS::exists(__st)) - *__ec = make_error_code(errc::no_such_file_or_directory); - else if (__ec) - __ec->clear(); - return __data_.__type_; - } - } - _LIBCPP_UNREACHABLE(); - } - - _LIBCPP_INLINE_VISIBILITY - file_status __get_status(error_code *__ec = nullptr) const { - switch (__data_.__cache_type_) { - case _Empty: - case _IterNonSymlink: - case _IterSymlink: - case _RefreshSymlinkUnresolved: - return __status(__p_, __ec); - case _RefreshNonSymlink: - case _RefreshSymlink: - return file_status(__get_ft(__ec), __data_.__non_sym_perms_); - } - _LIBCPP_UNREACHABLE(); - } - - _LIBCPP_INLINE_VISIBILITY - file_status __get_symlink_status(error_code *__ec = nullptr) const { - switch (__data_.__cache_type_) { - case _Empty: - case _IterNonSymlink: - case _IterSymlink: - return __symlink_status(__p_, __ec); - case _RefreshNonSymlink: - return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_); - case _RefreshSymlink: - case _RefreshSymlinkUnresolved: - return file_status(__get_sym_ft(__ec), __data_.__sym_perms_); - } - _LIBCPP_UNREACHABLE(); - } - - - _LIBCPP_INLINE_VISIBILITY - uintmax_t __get_size(error_code *__ec = nullptr) const { - switch (__data_.__cache_type_) { - case _Empty: - case _IterNonSymlink: - case _IterSymlink: - case _RefreshSymlinkUnresolved: - return _VSTD_FS::__file_size(__p_, __ec); - case _RefreshSymlink: - case _RefreshNonSymlink: { - error_code __m_ec; - file_status __st(__get_ft(&__m_ec)); - __handle_error("in directory_entry::file_size", __ec, __m_ec); - if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) { - errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory - : errc::not_supported; - __handle_error("in directory_entry::file_size", __ec, - make_error_code(__err_kind)); - } - return __data_.__size_; - } - } - _LIBCPP_UNREACHABLE(); - } - - _LIBCPP_INLINE_VISIBILITY - uintmax_t __get_nlink(error_code *__ec = nullptr) const { - switch (__data_.__cache_type_) { - case _Empty: - case _IterNonSymlink: - case _IterSymlink: - case _RefreshSymlinkUnresolved: - return _VSTD_FS::__hard_link_count(__p_, __ec); - case _RefreshSymlink: - case _RefreshNonSymlink: { - error_code __m_ec; - (void)__get_ft(&__m_ec); - __handle_error("in directory_entry::hard_link_count", __ec, __m_ec); - return __data_.__nlink_; - } - } - _LIBCPP_UNREACHABLE(); - } - - _LIBCPP_INLINE_VISIBILITY - file_time_type __get_write_time(error_code *__ec = nullptr) const { - switch (__data_.__cache_type_) { - case _Empty: - case _IterNonSymlink: - case _IterSymlink: - case _RefreshSymlinkUnresolved: - return _VSTD_FS::__last_write_time(__p_, __ec); - case _RefreshSymlink: - case _RefreshNonSymlink: { - error_code __m_ec; - file_status __st(__get_ft(&__m_ec)); - __handle_error("in directory_entry::last_write_time", __ec, __m_ec); - if (_VSTD_FS::exists(__st) && - __data_.__write_time_ == file_time_type::min()) - __handle_error("in directory_entry::last_write_time", __ec, - make_error_code(errc::value_too_large)); - return __data_.__write_time_; - } - } - _LIBCPP_UNREACHABLE(); - } -private: - _Path __p_; - __cached_data __data_; -}; - -class __dir_element_proxy { -public: - - inline _LIBCPP_INLINE_VISIBILITY - directory_entry operator*() { return _VSTD::move(__elem_); } - -private: - friend class directory_iterator; - friend class recursive_directory_iterator; - explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {} - __dir_element_proxy(__dir_element_proxy&& __o) : __elem_(_VSTD::move(__o.__elem_)) {} - directory_entry __elem_; -}; - -class directory_iterator -{ -public: - typedef directory_entry value_type; - typedef ptrdiff_t difference_type; - typedef value_type const* pointer; - typedef value_type const& reference; - typedef input_iterator_tag iterator_category; - -public: - //ctor & dtor - directory_iterator() noexcept - { } - - explicit directory_iterator(const path& __p) - : directory_iterator(__p, nullptr) - { } - - directory_iterator(const path& __p, directory_options __opts) - : directory_iterator(__p, nullptr, __opts) - { } - - directory_iterator(const path& __p, error_code& __ec) - : directory_iterator(__p, &__ec) - { } - - directory_iterator(const path& __p, directory_options __opts, - error_code& __ec) - : directory_iterator(__p, &__ec, __opts) - { } - - directory_iterator(const directory_iterator&) = default; - directory_iterator(directory_iterator&&) = default; - directory_iterator& operator=(const directory_iterator&) = default; - - directory_iterator& operator=(directory_iterator&& __o) noexcept { - // non-default implementation provided to support self-move assign. - if (this != &__o) { - __imp_ = _VSTD::move(__o.__imp_); - } - return *this; - } - - ~directory_iterator() = default; - - const directory_entry& operator*() const { - _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced"); - return __dereference(); - } - - const directory_entry* operator->() const - { return &**this; } - - directory_iterator& operator++() - { return __increment(); } - - __dir_element_proxy operator++(int) { - __dir_element_proxy __p(**this); - __increment(); - return __p; - } - - directory_iterator& increment(error_code& __ec) - { return __increment(&__ec); } - -private: - inline _LIBCPP_INLINE_VISIBILITY - friend bool operator==(const directory_iterator& __lhs, - const directory_iterator& __rhs) noexcept; - - // construct the dir_stream - _LIBCPP_FUNC_VIS - directory_iterator(const path&, error_code *, - directory_options = directory_options::none); - - _LIBCPP_FUNC_VIS - directory_iterator& __increment(error_code * __ec = nullptr); - - _LIBCPP_FUNC_VIS - const directory_entry& __dereference() const; - -private: - shared_ptr<__dir_stream> __imp_; -}; - - -inline _LIBCPP_INLINE_VISIBILITY -bool operator==(const directory_iterator& __lhs, - const directory_iterator& __rhs) noexcept { - return __lhs.__imp_ == __rhs.__imp_; -} - -inline _LIBCPP_INLINE_VISIBILITY -bool operator!=(const directory_iterator& __lhs, - const directory_iterator& __rhs) noexcept { - return !(__lhs == __rhs); -} - -// enable directory_iterator range-based for statements -inline _LIBCPP_INLINE_VISIBILITY -directory_iterator begin(directory_iterator __iter) noexcept { - return __iter; -} - -inline _LIBCPP_INLINE_VISIBILITY -directory_iterator end(const directory_iterator&) noexcept { - return directory_iterator(); -} - -class recursive_directory_iterator { -public: - using value_type = directory_entry; - using difference_type = std::ptrdiff_t; - using pointer = directory_entry const *; - using reference = directory_entry const &; - using iterator_category = std::input_iterator_tag; - -public: - // constructors and destructor - _LIBCPP_INLINE_VISIBILITY - recursive_directory_iterator() noexcept - : __rec_(false) - {} - - _LIBCPP_INLINE_VISIBILITY - explicit recursive_directory_iterator(const path& __p, - directory_options __xoptions = directory_options::none) - : recursive_directory_iterator(__p, __xoptions, nullptr) - { } - - _LIBCPP_INLINE_VISIBILITY - recursive_directory_iterator(const path& __p, - directory_options __xoptions, error_code& __ec) - : recursive_directory_iterator(__p, __xoptions, &__ec) - { } - - _LIBCPP_INLINE_VISIBILITY - recursive_directory_iterator(const path& __p, error_code& __ec) - : recursive_directory_iterator(__p, directory_options::none, &__ec) - { } - - recursive_directory_iterator(const recursive_directory_iterator&) = default; - recursive_directory_iterator(recursive_directory_iterator&&) = default; - - recursive_directory_iterator & - operator=(const recursive_directory_iterator&) = default; - - _LIBCPP_INLINE_VISIBILITY - recursive_directory_iterator & - operator=(recursive_directory_iterator&& __o) noexcept { - // non-default implementation provided to support self-move assign. - if (this != &__o) { - __imp_ = _VSTD::move(__o.__imp_); - __rec_ = __o.__rec_; - } - return *this; - } - - ~recursive_directory_iterator() = default; - - _LIBCPP_INLINE_VISIBILITY - const directory_entry& operator*() const - { return __dereference(); } - - _LIBCPP_INLINE_VISIBILITY - const directory_entry* operator->() const - { return &__dereference(); } - - recursive_directory_iterator& operator++() - { return __increment(); } - - _LIBCPP_INLINE_VISIBILITY - __dir_element_proxy operator++(int) { - __dir_element_proxy __p(**this); - __increment(); - return __p; - } - - _LIBCPP_INLINE_VISIBILITY - recursive_directory_iterator& increment(error_code& __ec) - { return __increment(&__ec); } - - _LIBCPP_FUNC_VIS directory_options options() const; - _LIBCPP_FUNC_VIS int depth() const; - - _LIBCPP_INLINE_VISIBILITY - void pop() { __pop(); } - - _LIBCPP_INLINE_VISIBILITY - void pop(error_code& __ec) - { __pop(&__ec); } - - _LIBCPP_INLINE_VISIBILITY - bool recursion_pending() const - { return __rec_; } - - _LIBCPP_INLINE_VISIBILITY - void disable_recursion_pending() - { __rec_ = false; } - -private: - recursive_directory_iterator(const path& __p, directory_options __opt, - error_code *__ec); - - _LIBCPP_FUNC_VIS - const directory_entry& __dereference() const; - - _LIBCPP_FUNC_VIS - bool __try_recursion(error_code* __ec); - - _LIBCPP_FUNC_VIS - void __advance(error_code* __ec=nullptr); - - _LIBCPP_FUNC_VIS - recursive_directory_iterator& __increment(error_code *__ec=nullptr); - - _LIBCPP_FUNC_VIS - void __pop(error_code* __ec=nullptr); - - inline _LIBCPP_INLINE_VISIBILITY - friend bool operator==(const recursive_directory_iterator&, - const recursive_directory_iterator&) noexcept; - - struct __shared_imp; - shared_ptr<__shared_imp> __imp_; - bool __rec_; -}; // class recursive_directory_iterator - - -inline _LIBCPP_INLINE_VISIBILITY -bool operator==(const recursive_directory_iterator& __lhs, - const recursive_directory_iterator& __rhs) noexcept -{ - return __lhs.__imp_ == __rhs.__imp_; -} - -_LIBCPP_INLINE_VISIBILITY -inline bool operator!=(const recursive_directory_iterator& __lhs, - const recursive_directory_iterator& __rhs) noexcept -{ - return !(__lhs == __rhs); -} -// enable recursive_directory_iterator range-based for statements -inline _LIBCPP_INLINE_VISIBILITY -recursive_directory_iterator begin(recursive_directory_iterator __iter) noexcept { - return __iter; -} - -inline _LIBCPP_INLINE_VISIBILITY -recursive_directory_iterator end(const recursive_directory_iterator&) noexcept { - return recursive_directory_iterator(); -} +using namespace _VSTD_FS; _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM diff --git a/include/filesystem b/include/filesystem new file mode 100644 index 000000000..aa1d71800 --- /dev/null +++ b/include/filesystem @@ -0,0 +1,2682 @@ +// -*- C++ -*- +//===--------------------------- filesystem -------------------------------===// +// +// 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_FILESYSTEM +#define _LIBCPP_FILESYSTEM +/* + filesystem synopsis + + namespace std { namespace filesystem { + + class path; + + void swap(path& lhs, path& rhs) noexcept; + size_t hash_value(const path& p) noexcept; + + bool operator==(const path& lhs, const path& rhs) noexcept; + bool operator!=(const path& lhs, const path& rhs) noexcept; + bool operator< (const path& lhs, const path& rhs) noexcept; + bool operator<=(const path& lhs, const path& rhs) noexcept; + bool operator> (const path& lhs, const path& rhs) noexcept; + bool operator>=(const path& lhs, const path& rhs) noexcept; + + path operator/ (const path& lhs, const path& rhs); + + // fs.path.io operators are friends of path. + template + friend basic_ostream& + operator<<(basic_ostream& os, const path& p); + + template + friend basic_istream& + operator>>(basic_istream& is, path& p); + + template + path u8path(const Source& source); + template + path u8path(InputIterator first, InputIterator last); + + class filesystem_error; + class directory_entry; + + class directory_iterator; + + // enable directory_iterator range-based for statements + directory_iterator begin(directory_iterator iter) noexcept; + directory_iterator end(const directory_iterator&) noexcept; + + class recursive_directory_iterator; + + // enable recursive_directory_iterator range-based for statements + recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept; + recursive_directory_iterator end(const recursive_directory_iterator&) noexcept; + + class file_status; + + struct space_info + { + uintmax_t capacity; + uintmax_t free; + uintmax_t available; + }; + + enum class file_type; + enum class perms; + enum class perm_options; + enum class copy_options; + enum class directory_options; + + typedef chrono::time_point file_time_type; + + // operational functions + + path absolute(const path& p); + path absolute(const path& p, error_code &ec); + + path canonical(const path& p); + path canonical(const path& p, error_code& ec); + + void copy(const path& from, const path& to); + void copy(const path& from, const path& to, error_code& ec); + void copy(const path& from, const path& to, copy_options options); + void copy(const path& from, const path& to, copy_options options, + error_code& ec); + + bool copy_file(const path& from, const path& to); + bool copy_file(const path& from, const path& to, error_code& ec); + bool copy_file(const path& from, const path& to, copy_options option); + bool copy_file(const path& from, const path& to, copy_options option, + error_code& ec); + + void copy_symlink(const path& existing_symlink, const path& new_symlink); + void copy_symlink(const path& existing_symlink, const path& new_symlink, + error_code& ec) noexcept; + + bool create_directories(const path& p); + bool create_directories(const path& p, error_code& ec); + + bool create_directory(const path& p); + bool create_directory(const path& p, error_code& ec) noexcept; + + bool create_directory(const path& p, const path& attributes); + bool create_directory(const path& p, const path& attributes, + error_code& ec) noexcept; + + void create_directory_symlink(const path& to, const path& new_symlink); + void create_directory_symlink(const path& to, const path& new_symlink, + error_code& ec) noexcept; + + void create_hard_link(const path& to, const path& new_hard_link); + void create_hard_link(const path& to, const path& new_hard_link, + error_code& ec) noexcept; + + void create_symlink(const path& to, const path& new_symlink); + void create_symlink(const path& to, const path& new_symlink, + error_code& ec) noexcept; + + path current_path(); + path current_path(error_code& ec); + void current_path(const path& p); + void current_path(const path& p, error_code& ec) noexcept; + + bool exists(file_status s) noexcept; + bool exists(const path& p); + bool exists(const path& p, error_code& ec) noexcept; + + bool equivalent(const path& p1, const path& p2); + bool equivalent(const path& p1, const path& p2, error_code& ec) noexcept; + + uintmax_t file_size(const path& p); + uintmax_t file_size(const path& p, error_code& ec) noexcept; + + uintmax_t hard_link_count(const path& p); + uintmax_t hard_link_count(const path& p, error_code& ec) noexcept; + + bool is_block_file(file_status s) noexcept; + bool is_block_file(const path& p); + bool is_block_file(const path& p, error_code& ec) noexcept; + + bool is_character_file(file_status s) noexcept; + bool is_character_file(const path& p); + bool is_character_file(const path& p, error_code& ec) noexcept; + + bool is_directory(file_status s) noexcept; + bool is_directory(const path& p); + bool is_directory(const path& p, error_code& ec) noexcept; + + bool is_empty(const path& p); + bool is_empty(const path& p, error_code& ec) noexcept; + + bool is_fifo(file_status s) noexcept; + bool is_fifo(const path& p); + bool is_fifo(const path& p, error_code& ec) noexcept; + + bool is_other(file_status s) noexcept; + bool is_other(const path& p); + bool is_other(const path& p, error_code& ec) noexcept; + + bool is_regular_file(file_status s) noexcept; + bool is_regular_file(const path& p); + bool is_regular_file(const path& p, error_code& ec) noexcept; + + bool is_socket(file_status s) noexcept; + bool is_socket(const path& p); + bool is_socket(const path& p, error_code& ec) noexcept; + + bool is_symlink(file_status s) noexcept; + bool is_symlink(const path& p); + bool is_symlink(const path& p, error_code& ec) noexcept; + + file_time_type last_write_time(const path& p); + file_time_type last_write_time(const path& p, error_code& ec) noexcept; + void last_write_time(const path& p, file_time_type new_time); + void last_write_time(const path& p, file_time_type new_time, + error_code& ec) noexcept; + + void permissions(const path& p, perms prms, + perm_options opts=perm_options::replace); + void permissions(const path& p, perms prms, error_code& ec) noexcept; + void permissions(const path& p, perms prms, perm_options opts, + error_code& ec); + + path proximate(const path& p, error_code& ec); + path proximate(const path& p, const path& base = current_path()); + path proximate(const path& p, const path& base, error_code &ec); + + path read_symlink(const path& p); + path read_symlink(const path& p, error_code& ec); + + path relative(const path& p, error_code& ec); + path relative(const path& p, const path& base=current_path()); + path relative(const path& p, const path& base, error_code& ec); + + bool remove(const path& p); + bool remove(const path& p, error_code& ec) noexcept; + + uintmax_t remove_all(const path& p); + uintmax_t remove_all(const path& p, error_code& ec); + + void rename(const path& from, const path& to); + void rename(const path& from, const path& to, error_code& ec) noexcept; + + void resize_file(const path& p, uintmax_t size); + void resize_file(const path& p, uintmax_t size, error_code& ec) noexcept; + + space_info space(const path& p); + space_info space(const path& p, error_code& ec) noexcept; + + file_status status(const path& p); + file_status status(const path& p, error_code& ec) noexcept; + + bool status_known(file_status s) noexcept; + + file_status symlink_status(const path& p); + file_status symlink_status(const path& p, error_code& ec) noexcept; + + path temp_directory_path(); + path temp_directory_path(error_code& ec); + + path weakly_canonical(path const& p); + path weakly_canonical(path const& p, error_code& ec); + + +} } // namespaces std::filesystem + +*/ + +#include <__config> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for quoted +#include + +#include <__debug> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_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 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 __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 __secs; + return time_point(__secs(__t)); + } +}; + +typedef chrono::time_point<_FilesystemClock> file_time_type; + +struct _LIBCPP_TYPE_VIS space_info { + uintmax_t capacity; + uintmax_t free; + uintmax_t available; +}; + +enum class _LIBCPP_ENUM_VIS file_type : signed char { + none = 0, + not_found = -1, + regular = 1, + directory = 2, + symlink = 3, + block = 4, + character = 5, + fifo = 6, + socket = 7, + unknown = 8 +}; + +enum class _LIBCPP_ENUM_VIS perms : unsigned { + none = 0, + + owner_read = 0400, + owner_write = 0200, + owner_exec = 0100, + owner_all = 0700, + + group_read = 040, + group_write = 020, + group_exec = 010, + group_all = 070, + + others_read = 04, + others_write = 02, + others_exec = 01, + others_all = 07, + + all = 0777, + + set_uid = 04000, + set_gid = 02000, + sticky_bit = 01000, + mask = 07777, + unknown = 0xFFFF, +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator&(perms _LHS, perms _RHS) { + return static_cast(static_cast(_LHS) & + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator|(perms _LHS, perms _RHS) { + return static_cast(static_cast(_LHS) | + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator^(perms _LHS, perms _RHS) { + return static_cast(static_cast(_LHS) ^ + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perms operator~(perms _LHS) { + return static_cast(~static_cast(_LHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline perms& operator&=(perms& _LHS, perms _RHS) { return _LHS = _LHS & _RHS; } + +_LIBCPP_INLINE_VISIBILITY +inline perms& operator|=(perms& _LHS, perms _RHS) { return _LHS = _LHS | _RHS; } + +_LIBCPP_INLINE_VISIBILITY +inline perms& operator^=(perms& _LHS, perms _RHS) { return _LHS = _LHS ^ _RHS; } + +enum class _LIBCPP_ENUM_VIS perm_options : unsigned char { + replace = 1, + add = 2, + remove = 4, + nofollow = 8 +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator&(perm_options _LHS, perm_options _RHS) { + return static_cast(static_cast(_LHS) & + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator|(perm_options _LHS, perm_options _RHS) { + return static_cast(static_cast(_LHS) | + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator^(perm_options _LHS, perm_options _RHS) { + return static_cast(static_cast(_LHS) ^ + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr perm_options operator~(perm_options _LHS) { + return static_cast(~static_cast(_LHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline perm_options& operator&=(perm_options& _LHS, perm_options _RHS) { + return _LHS = _LHS & _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +inline perm_options& operator|=(perm_options& _LHS, perm_options _RHS) { + return _LHS = _LHS | _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +inline perm_options& operator^=(perm_options& _LHS, perm_options _RHS) { + return _LHS = _LHS ^ _RHS; +} + +enum class _LIBCPP_ENUM_VIS copy_options : unsigned short { + none = 0, + skip_existing = 1, + overwrite_existing = 2, + update_existing = 4, + recursive = 8, + copy_symlinks = 16, + skip_symlinks = 32, + directories_only = 64, + create_symlinks = 128, + create_hard_links = 256, + __in_recursive_copy = 512, +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator&(copy_options _LHS, copy_options _RHS) { + return static_cast(static_cast(_LHS) & + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator|(copy_options _LHS, copy_options _RHS) { + return static_cast(static_cast(_LHS) | + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator^(copy_options _LHS, copy_options _RHS) { + return static_cast(static_cast(_LHS) ^ + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr copy_options operator~(copy_options _LHS) { + return static_cast(~static_cast(_LHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline copy_options& operator&=(copy_options& _LHS, copy_options _RHS) { + return _LHS = _LHS & _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +inline copy_options& operator|=(copy_options& _LHS, copy_options _RHS) { + return _LHS = _LHS | _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS) { + return _LHS = _LHS ^ _RHS; +} + +enum class _LIBCPP_ENUM_VIS directory_options : unsigned char { + none = 0, + follow_directory_symlink = 1, + skip_permission_denied = 2 +}; + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator&(directory_options _LHS, + directory_options _RHS) { + return static_cast(static_cast(_LHS) & + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator|(directory_options _LHS, + directory_options _RHS) { + return static_cast(static_cast(_LHS) | + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator^(directory_options _LHS, + directory_options _RHS) { + return static_cast(static_cast(_LHS) ^ + static_cast(_RHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline constexpr directory_options operator~(directory_options _LHS) { + return static_cast(~static_cast(_LHS)); +} + +_LIBCPP_INLINE_VISIBILITY +inline directory_options& operator&=(directory_options& _LHS, + directory_options _RHS) { + return _LHS = _LHS & _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +inline directory_options& operator|=(directory_options& _LHS, + directory_options _RHS) { + return _LHS = _LHS | _RHS; +} + +_LIBCPP_INLINE_VISIBILITY +inline directory_options& operator^=(directory_options& _LHS, + directory_options _RHS) { + return _LHS = _LHS ^ _RHS; +} + +class _LIBCPP_TYPE_VIS file_status { +public: + // constructors + _LIBCPP_INLINE_VISIBILITY + file_status() noexcept : file_status(file_type::none) {} + _LIBCPP_INLINE_VISIBILITY + explicit file_status(file_type __ft, perms __prms = perms::unknown) noexcept + : __ft_(__ft), + __prms_(__prms) {} + + file_status(const file_status&) noexcept = default; + file_status(file_status&&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY + ~file_status() {} + + file_status& operator=(const file_status&) noexcept = default; + file_status& operator=(file_status&&) noexcept = default; + + // observers + _LIBCPP_INLINE_VISIBILITY + file_type type() const noexcept { return __ft_; } + + _LIBCPP_INLINE_VISIBILITY + perms permissions() const noexcept { return __prms_; } + + // modifiers + _LIBCPP_INLINE_VISIBILITY + void type(file_type __ft) noexcept { __ft_ = __ft; } + + _LIBCPP_INLINE_VISIBILITY + void permissions(perms __p) noexcept { __prms_ = __p; } + +private: + file_type __ft_; + perms __prms_; +}; + +class _LIBCPP_TYPE_VIS directory_entry; + +template +struct __can_convert_char { + static const bool value = false; +}; +template +struct __can_convert_char : public __can_convert_char<_Tp> {}; +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char; +}; +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = wchar_t; +}; +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char16_t; +}; +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char32_t; +}; + +template +typename enable_if<__can_convert_char<_ECharT>::value, bool>::type +__is_separator(_ECharT __e) { + return __e == _ECharT('/'); +}; + +struct _NullSentinal {}; + +template +using _Void = void; + +template +struct __is_pathable_string : public false_type {}; + +template +struct __is_pathable_string< + basic_string<_ECharT, _Traits, _Alloc>, + _Void::__char_type> > + : public __can_convert_char<_ECharT> { + using _Str = basic_string<_ECharT, _Traits, _Alloc>; + using _Base = __can_convert_char<_ECharT>; + static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } + static _ECharT const* __range_end(_Str const& __s) { + return __s.data() + __s.length(); + } + static _ECharT __first_or_null(_Str const& __s) { + return __s.empty() ? _ECharT{} : __s[0]; + } +}; + +template +struct __is_pathable_string< + basic_string_view<_ECharT, _Traits>, + _Void::__char_type> > + : public __can_convert_char<_ECharT> { + using _Str = basic_string_view<_ECharT, _Traits>; + using _Base = __can_convert_char<_ECharT>; + static _ECharT const* __range_begin(_Str const& __s) { return __s.data(); } + static _ECharT const* __range_end(_Str const& __s) { + return __s.data() + __s.length(); + } + static _ECharT __first_or_null(_Str const& __s) { + return __s.empty() ? _ECharT{} : __s[0]; + } +}; + +template ::type, + class _UnqualPtrType = + typename remove_const::type>::type, + bool _IsCharPtr = is_pointer<_DS>::value&& + __can_convert_char<_UnqualPtrType>::value> +struct __is_pathable_char_array : false_type {}; + +template +struct __is_pathable_char_array<_Source, _ECharT*, _UPtr, true> + : __can_convert_char::type> { + using _Base = __can_convert_char::type>; + + static _ECharT const* __range_begin(const _ECharT* __b) { return __b; } + static _ECharT const* __range_end(const _ECharT* __b) { + using _Iter = const _ECharT*; + const _ECharT __sentinal = _ECharT{}; + _Iter __e = __b; + for (; *__e != __sentinal; ++__e) + ; + return __e; + } + + static _ECharT __first_or_null(const _ECharT* __b) { return *__b; } +}; + +template ::value, + class = void> +struct __is_pathable_iter : false_type {}; + +template +struct __is_pathable_iter< + _Iter, true, + _Void::value_type>::__char_type> > + : __can_convert_char::value_type> { + using _ECharT = typename iterator_traits<_Iter>::value_type; + using _Base = __can_convert_char<_ECharT>; + + static _Iter __range_begin(_Iter __b) { return __b; } + static _NullSentinal __range_end(_Iter) { return _NullSentinal{}; } + + static _ECharT __first_or_null(_Iter __b) { return *__b; } +}; + +template ::value, + bool _IsCharIterT = __is_pathable_char_array<_Tp>::value, + bool _IsIterT = !_IsCharIterT && __is_pathable_iter<_Tp>::value> +struct __is_pathable : false_type { + static_assert(!_IsStringT && !_IsCharIterT && !_IsIterT, "Must all be false"); +}; + +template +struct __is_pathable<_Tp, true, false, false> : __is_pathable_string<_Tp> {}; + +template +struct __is_pathable<_Tp, false, true, false> : __is_pathable_char_array<_Tp> { +}; + +template +struct __is_pathable<_Tp, false, false, true> : __is_pathable_iter<_Tp> {}; + +template +struct _PathCVT { + static_assert(__can_convert_char<_ECharT>::value, + "Char type not convertible"); + + typedef __narrow_to_utf8 _Narrower; + + static void __append_range(string& __dest, _ECharT const* __b, + _ECharT const* __e) { + _Narrower()(back_inserter(__dest), __b, __e); + } + + template + static void __append_range(string& __dest, _Iter __b, _Iter __e) { + static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload"); + if (__b == __e) + return; + basic_string<_ECharT> __tmp(__b, __e); + _Narrower()(back_inserter(__dest), __tmp.data(), + __tmp.data() + __tmp.length()); + } + + template + static void __append_range(string& __dest, _Iter __b, _NullSentinal) { + static_assert(!is_same<_Iter, _ECharT*>::value, "Call const overload"); + const _ECharT __sentinal = _ECharT{}; + if (*__b == __sentinal) + return; + basic_string<_ECharT> __tmp; + for (; *__b != __sentinal; ++__b) + __tmp.push_back(*__b); + _Narrower()(back_inserter(__dest), __tmp.data(), + __tmp.data() + __tmp.length()); + } + + template + static void __append_source(string& __dest, _Source const& __s) { + using _Traits = __is_pathable<_Source>; + __append_range(__dest, _Traits::__range_begin(__s), + _Traits::__range_end(__s)); + } +}; + +template <> +struct _PathCVT { + + template + static typename enable_if<__is_exactly_input_iterator<_Iter>::value>::type + __append_range(string& __dest, _Iter __b, _Iter __e) { + for (; __b != __e; ++__b) + __dest.push_back(*__b); + } + + template + static typename enable_if<__is_forward_iterator<_Iter>::value>::type + __append_range(string& __dest, _Iter __b, _Iter __e) { + __dest.__append_forward_unsafe(__b, __e); + } + + template + static void __append_range(string& __dest, _Iter __b, _NullSentinal) { + const char __sentinal = char{}; + for (; *__b != __sentinal; ++__b) + __dest.push_back(*__b); + } + + template + static void __append_source(string& __dest, _Source const& __s) { + using _Traits = __is_pathable<_Source>; + __append_range(__dest, _Traits::__range_begin(__s), + _Traits::__range_end(__s)); + } +}; + +class _LIBCPP_TYPE_VIS path { + template + using _EnableIfPathable = + typename enable_if<__is_pathable<_SourceOrIter>::value, _Tp>::type; + + template + using _SourceChar = typename __is_pathable<_Tp>::__char_type; + + template + using _SourceCVT = _PathCVT<_SourceChar<_Tp> >; + +public: + typedef char value_type; + typedef basic_string string_type; + typedef _VSTD::string_view __string_view; + static constexpr value_type preferred_separator = '/'; + + enum class _LIBCPP_ENUM_VIS format : unsigned char { + auto_format, + native_format, + generic_format + }; + + // constructors and destructor + _LIBCPP_INLINE_VISIBILITY path() noexcept {} + _LIBCPP_INLINE_VISIBILITY path(const path& __p) : __pn_(__p.__pn_) {} + _LIBCPP_INLINE_VISIBILITY path(path&& __p) noexcept + : __pn_(_VSTD::move(__p.__pn_)) {} + + _LIBCPP_INLINE_VISIBILITY + path(string_type&& __s, format = format::auto_format) noexcept + : __pn_(_VSTD::move(__s)) {} + + template > + path(const _Source& __src, format = format::auto_format) { + _SourceCVT<_Source>::__append_source(__pn_, __src); + } + + template + path(_InputIt __first, _InputIt __last, format = format::auto_format) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); + } + + // TODO Implement locale conversions. + template > + path(const _Source& __src, const locale& __loc, format = format::auto_format); + template + path(_InputIt __first, _InputIt _last, const locale& __loc, + format = format::auto_format); + + _LIBCPP_INLINE_VISIBILITY + ~path() = default; + + // assignments + _LIBCPP_INLINE_VISIBILITY + path& operator=(const path& __p) { + __pn_ = __p.__pn_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator=(path&& __p) noexcept { + __pn_ = _VSTD::move(__p.__pn_); + return *this; + } + + template + _LIBCPP_INLINE_VISIBILITY path& operator=(string_type&& __s) noexcept { + __pn_ = _VSTD::move(__s); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& assign(string_type&& __s) noexcept { + __pn_ = _VSTD::move(__s); + return *this; + } + + template + _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source> + operator=(const _Source& __src) { + return this->assign(__src); + } + + template + _EnableIfPathable<_Source> assign(const _Source& __src) { + __pn_.clear(); + _SourceCVT<_Source>::__append_source(__pn_, __src); + return *this; + } + + template + path& assign(_InputIt __first, _InputIt __last) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + __pn_.clear(); + _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); + return *this; + } + +private: + template + static bool __source_is_absolute(_ECharT __first_or_null) { + return __is_separator(__first_or_null); + } + +public: + // appends + path& operator/=(const path& __p) { + if (__p.is_absolute()) { + __pn_ = __p.__pn_; + return *this; + } + if (has_filename()) + __pn_ += preferred_separator; + __pn_ += __p.native(); + return *this; + } + + // FIXME: Use _LIBCPP_DIAGNOSE_WARNING to produce a diagnostic when __src + // is known at compile time to be "/' since the user almost certainly intended + // to append a separator instead of overwriting the path with "/" + template + _LIBCPP_INLINE_VISIBILITY _EnableIfPathable<_Source> + operator/=(const _Source& __src) { + return this->append(__src); + } + + template + _EnableIfPathable<_Source> append(const _Source& __src) { + using _Traits = __is_pathable<_Source>; + using _CVT = _PathCVT<_SourceChar<_Source> >; + if (__source_is_absolute(_Traits::__first_or_null(__src))) + __pn_.clear(); + else if (has_filename()) + __pn_ += preferred_separator; + _CVT::__append_source(__pn_, __src); + return *this; + } + + template + path& append(_InputIt __first, _InputIt __last) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + static_assert(__can_convert_char<_ItVal>::value, "Must convertible"); + using _CVT = _PathCVT<_ItVal>; + if (__first != __last && __source_is_absolute(*__first)) + __pn_.clear(); + else if (has_filename()) + __pn_ += preferred_separator; + _CVT::__append_range(__pn_, __first, __last); + return *this; + } + + // concatenation + _LIBCPP_INLINE_VISIBILITY + path& operator+=(const path& __x) { + __pn_ += __x.__pn_; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator+=(const string_type& __x) { + __pn_ += __x; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator+=(__string_view __x) { + __pn_ += __x; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator+=(const value_type* __x) { + __pn_ += __x; + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + path& operator+=(value_type __x) { + __pn_ += __x; + return *this; + } + + template + typename enable_if<__can_convert_char<_ECharT>::value, path&>::type + operator+=(_ECharT __x) { + basic_string<_ECharT> __tmp; + __tmp += __x; + _PathCVT<_ECharT>::__append_source(__pn_, __tmp); + return *this; + } + + template + _EnableIfPathable<_Source> operator+=(const _Source& __x) { + return this->concat(__x); + } + + template + _EnableIfPathable<_Source> concat(const _Source& __x) { + _SourceCVT<_Source>::__append_source(__pn_, __x); + return *this; + } + + template + path& concat(_InputIt __first, _InputIt __last) { + typedef typename iterator_traits<_InputIt>::value_type _ItVal; + _PathCVT<_ItVal>::__append_range(__pn_, __first, __last); + return *this; + } + + // modifiers + _LIBCPP_INLINE_VISIBILITY + void clear() noexcept { __pn_.clear(); } + + path& make_preferred() { return *this; } + + _LIBCPP_INLINE_VISIBILITY + path& remove_filename() { + auto __fname = __filename(); + if (!__fname.empty()) + __pn_.erase(__fname.data() - __pn_.data()); + return *this; + } + + path& replace_filename(const path& __replacement) { + remove_filename(); + return (*this /= __replacement); + } + + path& replace_extension(const path& __replacement = path()); + + _LIBCPP_INLINE_VISIBILITY + void swap(path& __rhs) noexcept { __pn_.swap(__rhs.__pn_); } + + // private helper to allow reserving memory in the path + _LIBCPP_INLINE_VISIBILITY + void __reserve(size_t __s) { __pn_.reserve(__s); } + + // native format observers + _LIBCPP_INLINE_VISIBILITY + const string_type& native() const noexcept { return __pn_; } + + _LIBCPP_INLINE_VISIBILITY + const value_type* c_str() const noexcept { return __pn_.c_str(); } + + _LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; } + + template , + class _Allocator = allocator<_ECharT> > + basic_string<_ECharT, _Traits, _Allocator> + string(const _Allocator& __a = _Allocator()) const { + using _CVT = __widen_from_utf8; + using _Str = basic_string<_ECharT, _Traits, _Allocator>; + _Str __s(__a); + __s.reserve(__pn_.size()); + _CVT()(back_inserter(__s), __pn_.data(), __pn_.data() + __pn_.size()); + return __s; + } + + _LIBCPP_INLINE_VISIBILITY std::string string() const { return __pn_; } + _LIBCPP_INLINE_VISIBILITY std::wstring wstring() const { + return string(); + } + _LIBCPP_INLINE_VISIBILITY std::string u8string() const { return __pn_; } + _LIBCPP_INLINE_VISIBILITY std::u16string u16string() const { + return string(); + } + _LIBCPP_INLINE_VISIBILITY std::u32string u32string() const { + return string(); + } + + // generic format observers + template , + class _Allocator = allocator<_ECharT> > + basic_string<_ECharT, _Traits, _Allocator> + generic_string(const _Allocator& __a = _Allocator()) const { + return string<_ECharT, _Traits, _Allocator>(__a); + } + + std::string generic_string() const { return __pn_; } + std::wstring generic_wstring() const { return string(); } + std::string generic_u8string() const { return __pn_; } + std::u16string generic_u16string() const { return string(); } + std::u32string generic_u32string() const { return string(); } + +private: + int __compare(__string_view) const; + __string_view __root_name() const; + __string_view __root_directory() const; + __string_view __root_path_raw() const; + __string_view __relative_path() const; + __string_view __parent_path() const; + __string_view __filename() const; + __string_view __stem() const; + __string_view __extension() const; + +public: + // compare + _LIBCPP_INLINE_VISIBILITY int compare(const path& __p) const noexcept { + return __compare(__p.__pn_); + } + _LIBCPP_INLINE_VISIBILITY int compare(const string_type& __s) const { + return __compare(__s); + } + _LIBCPP_INLINE_VISIBILITY int compare(__string_view __s) const { + return __compare(__s); + } + _LIBCPP_INLINE_VISIBILITY int compare(const value_type* __s) const { + return __compare(__s); + } + + // decomposition + _LIBCPP_INLINE_VISIBILITY path root_name() const { + return string_type(__root_name()); + } + _LIBCPP_INLINE_VISIBILITY path root_directory() const { + return string_type(__root_directory()); + } + _LIBCPP_INLINE_VISIBILITY path root_path() const { + return root_name().append(string_type(__root_directory())); + } + _LIBCPP_INLINE_VISIBILITY path relative_path() const { + return string_type(__relative_path()); + } + _LIBCPP_INLINE_VISIBILITY path parent_path() const { + return string_type(__parent_path()); + } + _LIBCPP_INLINE_VISIBILITY path filename() const { + return string_type(__filename()); + } + _LIBCPP_INLINE_VISIBILITY path stem() const { return string_type(__stem()); } + _LIBCPP_INLINE_VISIBILITY path extension() const { + return string_type(__extension()); + } + + // query + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY bool + empty() const noexcept { + return __pn_.empty(); + } + + _LIBCPP_INLINE_VISIBILITY bool has_root_name() const { + return !__root_name().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_root_directory() const { + return !__root_directory().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_root_path() const { + return !__root_path_raw().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_relative_path() const { + return !__relative_path().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_parent_path() const { + return !__parent_path().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_filename() const { + return !__filename().empty(); + } + _LIBCPP_INLINE_VISIBILITY bool has_stem() const { return !__stem().empty(); } + _LIBCPP_INLINE_VISIBILITY bool has_extension() const { + return !__extension().empty(); + } + + _LIBCPP_INLINE_VISIBILITY bool is_absolute() const { + return has_root_directory(); + } + _LIBCPP_INLINE_VISIBILITY bool is_relative() const { return !is_absolute(); } + + // relative paths + path lexically_normal() const; + path lexically_relative(const path& __base) const; + + _LIBCPP_INLINE_VISIBILITY path lexically_proximate(const path& __base) const { + path __result = this->lexically_relative(__base); + if (__result.native().empty()) + return *this; + return __result; + } + + // iterators + class _LIBCPP_TYPE_VIS iterator; + typedef iterator const_iterator; + + iterator begin() const; + iterator end() const; + + template + _LIBCPP_INLINE_VISIBILITY friend + typename enable_if::value && + is_same<_Traits, char_traits >::value, + basic_ostream<_CharT, _Traits>&>::type + operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) { + __os << std::__quoted(__p.native()); + return __os; + } + + template + _LIBCPP_INLINE_VISIBILITY friend + typename enable_if::value || + !is_same<_Traits, char_traits >::value, + basic_ostream<_CharT, _Traits>&>::type + operator<<(basic_ostream<_CharT, _Traits>& __os, const path& __p) { + __os << std::__quoted(__p.string<_CharT, _Traits>()); + return __os; + } + + template + _LIBCPP_INLINE_VISIBILITY friend basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __is, path& __p) { + basic_string<_CharT, _Traits> __tmp; + __is >> __quoted(__tmp); + __p = __tmp; + return __is; + } + +private: + inline _LIBCPP_INLINE_VISIBILITY path& + __assign_view(__string_view const& __s) noexcept { + __pn_ = string_type(__s); + return *this; + } + string_type __pn_; +}; + +inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept { + __lhs.swap(__rhs); +} + +_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 +_LIBCPP_INLINE_VISIBILITY + typename enable_if<__is_pathable<_Source>::value, path>::type + u8path(const _Source& __s) { + static_assert( + is_same::__char_type, char>::value, + "u8path(Source const&) requires Source have a character type of type " + "'char'"); + return path(__s); +} + +template +_LIBCPP_INLINE_VISIBILITY + typename enable_if<__is_pathable<_InputIt>::value, path>::type + u8path(_InputIt __f, _InputIt __l) { + static_assert( + is_same::__char_type, char>::value, + "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"); + return path(__f, __l); +} + +class _LIBCPP_TYPE_VIS path::iterator { +public: + enum _ParserState : unsigned char { + _Singular, + _BeforeBegin, + _InRootName, + _InRootDir, + _InFilenames, + _InTrailingSep, + _AtEnd + }; + +public: + typedef bidirectional_iterator_tag iterator_category; + + typedef path value_type; + typedef std::ptrdiff_t difference_type; + typedef const path* pointer; + typedef const path& reference; + + typedef void + __stashing_iterator_tag; // See reverse_iterator and __is_stashing_iterator + +public: + _LIBCPP_INLINE_VISIBILITY + iterator() + : __stashed_elem_(), __path_ptr_(nullptr), __entry_(), + __state_(_Singular) {} + + iterator(const iterator&) = default; + ~iterator() = default; + + iterator& operator=(const iterator&) = default; + + _LIBCPP_INLINE_VISIBILITY + reference operator*() const { return __stashed_elem_; } + + _LIBCPP_INLINE_VISIBILITY + pointer operator->() const { return &__stashed_elem_; } + + _LIBCPP_INLINE_VISIBILITY + iterator& operator++() { + _LIBCPP_ASSERT(__state_ != _Singular, + "attempting to increment a singular iterator"); + _LIBCPP_ASSERT(__state_ != _AtEnd, + "attempting to increment the end iterator"); + return __increment(); + } + + _LIBCPP_INLINE_VISIBILITY + iterator operator++(int) { + iterator __it(*this); + this->operator++(); + return __it; + } + + _LIBCPP_INLINE_VISIBILITY + iterator& operator--() { + _LIBCPP_ASSERT(__state_ != _Singular, + "attempting to decrement a singular iterator"); + _LIBCPP_ASSERT(__entry_.data() != __path_ptr_->native().data(), + "attempting to decrement the begin iterator"); + return __decrement(); + } + + _LIBCPP_INLINE_VISIBILITY + iterator operator--(int) { + iterator __it(*this); + this->operator--(); + return __it; + } + +private: + friend class path; + + inline _LIBCPP_INLINE_VISIBILITY friend bool operator==(const iterator&, + const iterator&); + + iterator& __increment(); + iterator& __decrement(); + + path __stashed_elem_; + const path* __path_ptr_; + path::__string_view __entry_; + _ParserState __state_; +}; + +inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path::iterator& __lhs, + const path::iterator& __rhs) { + return __lhs.__path_ptr_ == __rhs.__path_ptr_ && + __lhs.__entry_.data() == __rhs.__entry_.data(); +} + +inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path::iterator& __lhs, + const path::iterator& __rhs) { + return !(__lhs == __rhs); +} + +class _LIBCPP_EXCEPTION_ABI filesystem_error : public system_error { +public: + _LIBCPP_INLINE_VISIBILITY + filesystem_error(const string& __what, error_code __ec) + : system_error(__ec, __what), + __storage_(make_shared<_Storage>(path(), path())) { + __create_what(0); + } + + _LIBCPP_INLINE_VISIBILITY + filesystem_error(const string& __what, const path& __p1, error_code __ec) + : system_error(__ec, __what), + __storage_(make_shared<_Storage>(__p1, path())) { + __create_what(1); + } + + _LIBCPP_INLINE_VISIBILITY + filesystem_error(const string& __what, const path& __p1, const path& __p2, + error_code __ec) + : system_error(__ec, __what), + __storage_(make_shared<_Storage>(__p1, __p2)) { + __create_what(2); + } + + _LIBCPP_INLINE_VISIBILITY + const path& path1() const noexcept { return __storage_->__p1_; } + + _LIBCPP_INLINE_VISIBILITY + const path& path2() const noexcept { return __storage_->__p2_; } + + ~filesystem_error() override; // key function + + _LIBCPP_INLINE_VISIBILITY + const char* what() const noexcept override { + return __storage_->__what_.c_str(); + } + + _LIBCPP_FUNC_VIS + void __create_what(int __num_paths); + +private: + struct _Storage { + _LIBCPP_INLINE_VISIBILITY + _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {} + + path __p1_; + path __p2_; + string __what_; + }; + shared_ptr<_Storage> __storage_; +}; + +template +_LIBCPP_NORETURN inline _LIBCPP_INLINE_VISIBILITY +#ifndef _LIBCPP_NO_EXCEPTIONS + void + __throw_filesystem_error(_Args&&... __args) { + throw filesystem_error(std::forward<_Args>(__args)...); +} +#else + void + __throw_filesystem_error(_Args&&...) { + _VSTD::abort(); +} +#endif + +// operational functions + +_LIBCPP_FUNC_VIS +path __absolute(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +path __canonical(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +void __copy(const path& __from, const path& __to, copy_options __opt, + error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +bool __copy_file(const path& __from, const path& __to, copy_options __opt, + error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +void __copy_symlink(const path& __existing_symlink, const path& __new_symlink, + error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +bool __create_directories(const path& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +bool __create_directory(const path& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +bool __create_directory(const path& p, const path& attributes, + error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +void __create_directory_symlink(const path& __to, const path& __new_symlink, + error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +void __create_hard_link(const path& __to, const path& __new_hard_link, + error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +void __create_symlink(const path& __to, const path& __new_symlink, + error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +path __current_path(error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +void __current_path(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +bool __equivalent(const path&, const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +uintmax_t __file_size(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +uintmax_t __hard_link_count(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +bool __fs_is_empty(const path& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +file_time_type __last_write_time(const path& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +void __last_write_time(const path& p, file_time_type new_time, + error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +void __permissions(const path&, perms, perm_options, error_code* = nullptr); +_LIBCPP_FUNC_VIS +path __read_symlink(const path& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +bool __remove(const path& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +uintmax_t __remove_all(const path& p, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +void __rename(const path& from, const path& to, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +void __resize_file(const path& p, uintmax_t size, error_code* ec = nullptr); +_LIBCPP_FUNC_VIS +space_info __space(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +file_status __status(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +file_status __symlink_status(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +path __system_complete(const path&, error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +path __temp_directory_path(error_code* __ec = nullptr); +_LIBCPP_FUNC_VIS +path __weakly_canonical(path const& __p, error_code* __ec = nullptr); + +inline _LIBCPP_INLINE_VISIBILITY path current_path() { + return __current_path(); +} + +inline _LIBCPP_INLINE_VISIBILITY path current_path(error_code& __ec) { + return __current_path(&__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p) { + __current_path(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY void current_path(const path& __p, + error_code& __ec) noexcept { + __current_path(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p) { + return __absolute(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY path absolute(const path& __p, + error_code& __ec) { + return __absolute(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p) { + return __canonical(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY path canonical(const path& __p, + error_code& __ec) { + return __canonical(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, + const path& __to) { + __copy(__from, __to, copy_options::none); +} + +inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to, + error_code& __ec) { + __copy(__from, __to, copy_options::none, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to, + copy_options __opt) { + __copy(__from, __to, __opt); +} + +inline _LIBCPP_INLINE_VISIBILITY void copy(const path& __from, const path& __to, + copy_options __opt, + error_code& __ec) { + __copy(__from, __to, __opt, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from, + const path& __to) { + return __copy_file(__from, __to, copy_options::none); +} + +inline _LIBCPP_INLINE_VISIBILITY bool +copy_file(const path& __from, const path& __to, error_code& __ec) { + return __copy_file(__from, __to, copy_options::none, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY bool +copy_file(const path& __from, const path& __to, copy_options __opt) { + return __copy_file(__from, __to, __opt); +} + +inline _LIBCPP_INLINE_VISIBILITY bool copy_file(const path& __from, + const path& __to, + copy_options __opt, + error_code& __ec) { + return __copy_file(__from, __to, __opt, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void copy_symlink(const path& __existing, + const path& __new) { + __copy_symlink(__existing, __new); +} + +inline _LIBCPP_INLINE_VISIBILITY void +copy_symlink(const path& __ext, const path& __new, error_code& __ec) noexcept { + __copy_symlink(__ext, __new, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p) { + return __create_directories(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY bool create_directories(const path& __p, + error_code& __ec) { + return __create_directories(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p) { + return __create_directory(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY bool +create_directory(const path& __p, error_code& __ec) noexcept { + return __create_directory(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY bool create_directory(const path& __p, + const path& __attrs) { + return __create_directory(__p, __attrs); +} + +inline _LIBCPP_INLINE_VISIBILITY bool +create_directory(const path& __p, const path& __attrs, + error_code& __ec) noexcept { + return __create_directory(__p, __attrs, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void +create_directory_symlink(const path& __to, const path& __new) { + __create_directory_symlink(__to, __new); +} + +inline _LIBCPP_INLINE_VISIBILITY void +create_directory_symlink(const path& __to, const path& __new, + error_code& __ec) noexcept { + __create_directory_symlink(__to, __new, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void create_hard_link(const path& __to, + const path& __new) { + __create_hard_link(__to, __new); +} + +inline _LIBCPP_INLINE_VISIBILITY void +create_hard_link(const path& __to, const path& __new, + error_code& __ec) noexcept { + __create_hard_link(__to, __new, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void create_symlink(const path& __to, + const path& __new) { + __create_symlink(__to, __new); +} + +inline _LIBCPP_INLINE_VISIBILITY void +create_symlink(const path& __to, const path& __new, error_code& __ec) noexcept { + return __create_symlink(__to, __new, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY bool status_known(file_status __s) noexcept { + return __s.type() != file_type::none; +} + +inline _LIBCPP_INLINE_VISIBILITY bool exists(file_status __s) noexcept { + return status_known(__s) && __s.type() != file_type::not_found; +} + +inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p) { + return exists(__status(__p)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool exists(const path& __p, + error_code& __ec) noexcept { + auto __s = __status(__p, &__ec); + if (status_known(__s)) + __ec.clear(); + return exists(__s); +} + +inline _LIBCPP_INLINE_VISIBILITY bool equivalent(const path& __p1, + const path& __p2) { + return __equivalent(__p1, __p2); +} + +inline _LIBCPP_INLINE_VISIBILITY bool +equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept { + return __equivalent(__p1, __p2, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY uintmax_t file_size(const path& __p) { + return __file_size(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY uintmax_t +file_size(const path& __p, error_code& __ec) noexcept { + return __file_size(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY uintmax_t hard_link_count(const path& __p) { + return __hard_link_count(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY uintmax_t +hard_link_count(const path& __p, error_code& __ec) noexcept { + return __hard_link_count(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(file_status __s) noexcept { + return __s.type() == file_type::block; +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p) { + return is_block_file(__status(__p)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_block_file(const path& __p, + error_code& __ec) noexcept { + return is_block_file(__status(__p, &__ec)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool +is_character_file(file_status __s) noexcept { + return __s.type() == file_type::character; +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_character_file(const path& __p) { + return is_character_file(__status(__p)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool +is_character_file(const path& __p, error_code& __ec) noexcept { + return is_character_file(__status(__p, &__ec)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_directory(file_status __s) noexcept { + return __s.type() == file_type::directory; +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p) { + return is_directory(__status(__p)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_directory(const path& __p, + error_code& __ec) noexcept { + return is_directory(__status(__p, &__ec)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p) { + return __fs_is_empty(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_empty(const path& __p, + error_code& __ec) { + return __fs_is_empty(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(file_status __s) noexcept { + return __s.type() == file_type::fifo; +} +inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p) { + return is_fifo(__status(__p)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_fifo(const path& __p, + error_code& __ec) noexcept { + return is_fifo(__status(__p, &__ec)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool +is_regular_file(file_status __s) noexcept { + return __s.type() == file_type::regular; +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_regular_file(const path& __p) { + return is_regular_file(__status(__p)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool +is_regular_file(const path& __p, error_code& __ec) noexcept { + return is_regular_file(__status(__p, &__ec)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_socket(file_status __s) noexcept { + return __s.type() == file_type::socket; +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p) { + return is_socket(__status(__p)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_socket(const path& __p, + error_code& __ec) noexcept { + return is_socket(__status(__p, &__ec)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(file_status __s) noexcept { + return __s.type() == file_type::symlink; +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p) { + return is_symlink(__symlink_status(__p)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_symlink(const path& __p, + error_code& __ec) noexcept { + return is_symlink(__symlink_status(__p, &__ec)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_other(file_status __s) noexcept { + return exists(__s) && !is_regular_file(__s) && !is_directory(__s) && + !is_symlink(__s); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p) { + return is_other(__status(__p)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool is_other(const path& __p, + error_code& __ec) noexcept { + return is_other(__status(__p, &__ec)); +} + +inline _LIBCPP_INLINE_VISIBILITY file_time_type +last_write_time(const path& __p) { + return __last_write_time(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY file_time_type +last_write_time(const path& __p, error_code& __ec) noexcept { + return __last_write_time(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void last_write_time(const path& __p, + file_time_type __t) { + __last_write_time(__p, __t); +} + +inline _LIBCPP_INLINE_VISIBILITY void +last_write_time(const path& __p, file_time_type __t, + error_code& __ec) noexcept { + __last_write_time(__p, __t, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void +permissions(const path& __p, perms __prms, + perm_options __opts = perm_options::replace) { + __permissions(__p, __prms, __opts); +} + +inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms, + error_code& __ec) noexcept { + __permissions(__p, __prms, perm_options::replace, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void permissions(const path& __p, perms __prms, + perm_options __opts, + error_code& __ec) { + __permissions(__p, __prms, __opts, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p, + const path& __base, + error_code& __ec) { + path __tmp = __weakly_canonical(__p, &__ec); + if (__ec) + return {}; + path __tmp_base = __weakly_canonical(__base, &__ec); + if (__ec) + return {}; + return __tmp.lexically_proximate(__tmp_base); +} + +inline _LIBCPP_INLINE_VISIBILITY path proximate(const path& __p, + error_code& __ec) { + return proximate(__p, current_path(), __ec); +} + +inline _LIBCPP_INLINE_VISIBILITY path +proximate(const path& __p, const path& __base = current_path()) { + return __weakly_canonical(__p).lexically_proximate( + __weakly_canonical(__base)); +} + +inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p) { + return __read_symlink(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY path read_symlink(const path& __p, + error_code& __ec) { + return __read_symlink(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p, + const path& __base, + error_code& __ec) { + path __tmp = __weakly_canonical(__p, &__ec); + if (__ec) + return path(); + path __tmpbase = __weakly_canonical(__base, &__ec); + if (__ec) + return path(); + return __tmp.lexically_relative(__tmpbase); +} + +inline _LIBCPP_INLINE_VISIBILITY path relative(const path& __p, + error_code& __ec) { + return relative(__p, current_path(), __ec); +} + +inline _LIBCPP_INLINE_VISIBILITY path +relative(const path& __p, const path& __base = current_path()) { + return __weakly_canonical(__p).lexically_relative(__weakly_canonical(__base)); +} + +inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p) { + return __remove(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY bool remove(const path& __p, + error_code& __ec) noexcept { + return __remove(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p) { + return __remove_all(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY uintmax_t remove_all(const path& __p, + error_code& __ec) { + return __remove_all(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void rename(const path& __from, + const path& __to) { + return __rename(__from, __to); +} + +inline _LIBCPP_INLINE_VISIBILITY void +rename(const path& __from, const path& __to, error_code& __ec) noexcept { + return __rename(__from, __to, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY void resize_file(const path& __p, + uintmax_t __ns) { + return __resize_file(__p, __ns); +} + +inline _LIBCPP_INLINE_VISIBILITY void +resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept { + return __resize_file(__p, __ns, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p) { + return __space(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY space_info space(const path& __p, + error_code& __ec) noexcept { + return __space(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p) { + return __status(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY file_status status(const path& __p, + error_code& __ec) noexcept { + return __status(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY file_status symlink_status(const path& __p) { + return __symlink_status(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY file_status +symlink_status(const path& __p, error_code& __ec) noexcept { + return __symlink_status(__p, &__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path() { + return __temp_directory_path(); +} + +inline _LIBCPP_INLINE_VISIBILITY path temp_directory_path(error_code& __ec) { + return __temp_directory_path(&__ec); +} + +inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p) { + return __weakly_canonical(__p); +} + +inline _LIBCPP_INLINE_VISIBILITY path weakly_canonical(path const& __p, + error_code& __ec) { + return __weakly_canonical(__p, &__ec); +} + +class directory_iterator; +class recursive_directory_iterator; +class __dir_stream; + +class directory_entry { + typedef _VSTD_FS::path _Path; + +public: + // constructors and destructors + directory_entry() noexcept = default; + directory_entry(directory_entry const&) = default; + directory_entry(directory_entry&&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY + explicit directory_entry(_Path const& __p) : __p_(__p) { + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + directory_entry(_Path const& __p, error_code& __ec) : __p_(__p) { + __refresh(&__ec); + } + + ~directory_entry() {} + + directory_entry& operator=(directory_entry const&) = default; + directory_entry& operator=(directory_entry&&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY + void assign(_Path const& __p) { + __p_ = __p; + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void assign(_Path const& __p, error_code& __ec) { + __p_ = __p; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void replace_filename(_Path const& __p) { + __p_.replace_filename(__p); + error_code __ec; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void replace_filename(_Path const& __p, error_code& __ec) { + __p_ = __p_.parent_path() / __p; + __refresh(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + void refresh() { __refresh(); } + + _LIBCPP_INLINE_VISIBILITY + void refresh(error_code& __ec) noexcept { __refresh(&__ec); } + + _LIBCPP_INLINE_VISIBILITY + _Path const& path() const noexcept { return __p_; } + + _LIBCPP_INLINE_VISIBILITY + operator const _Path&() const noexcept { return __p_; } + + _LIBCPP_INLINE_VISIBILITY + bool exists() const { return _VSTD_FS::exists(file_status{__get_ft()}); } + + _LIBCPP_INLINE_VISIBILITY + bool exists(error_code& __ec) const noexcept { + return _VSTD_FS::exists(file_status{__get_ft(&__ec)}); + } + + _LIBCPP_INLINE_VISIBILITY + bool is_block_file() const { return __get_ft() == file_type::block; } + + _LIBCPP_INLINE_VISIBILITY + bool is_block_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::block; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_character_file() const { return __get_ft() == file_type::character; } + + _LIBCPP_INLINE_VISIBILITY + bool is_character_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::character; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_directory() const { return __get_ft() == file_type::directory; } + + _LIBCPP_INLINE_VISIBILITY + bool is_directory(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::directory; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_fifo() const { return __get_ft() == file_type::fifo; } + + _LIBCPP_INLINE_VISIBILITY + bool is_fifo(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::fifo; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_other() const { return _VSTD_FS::is_other(file_status{__get_ft()}); } + + _LIBCPP_INLINE_VISIBILITY + bool is_other(error_code& __ec) const noexcept { + return _VSTD_FS::is_other(file_status{__get_ft(&__ec)}); + } + + _LIBCPP_INLINE_VISIBILITY + bool is_regular_file() const { return __get_ft() == file_type::regular; } + + _LIBCPP_INLINE_VISIBILITY + bool is_regular_file(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::regular; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_socket() const { return __get_ft() == file_type::socket; } + + _LIBCPP_INLINE_VISIBILITY + bool is_socket(error_code& __ec) const noexcept { + return __get_ft(&__ec) == file_type::socket; + } + + _LIBCPP_INLINE_VISIBILITY + bool is_symlink() const { return __get_sym_ft() == file_type::symlink; } + + _LIBCPP_INLINE_VISIBILITY + bool is_symlink(error_code& __ec) const noexcept { + return __get_sym_ft(&__ec) == file_type::symlink; + } + _LIBCPP_INLINE_VISIBILITY + uintmax_t file_size() const { return __get_size(); } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t file_size(error_code& __ec) const noexcept { + return __get_size(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t hard_link_count() const { return __get_nlink(); } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t hard_link_count(error_code& __ec) const noexcept { + return __get_nlink(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + file_time_type last_write_time() const { return __get_write_time(); } + + _LIBCPP_INLINE_VISIBILITY + file_time_type last_write_time(error_code& __ec) const noexcept { + return __get_write_time(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + file_status status() const { return __get_status(); } + + _LIBCPP_INLINE_VISIBILITY + file_status status(error_code& __ec) const noexcept { + return __get_status(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + file_status symlink_status() const { return __get_symlink_status(); } + + _LIBCPP_INLINE_VISIBILITY + file_status symlink_status(error_code& __ec) const noexcept { + return __get_symlink_status(&__ec); + } + + _LIBCPP_INLINE_VISIBILITY + bool operator<(directory_entry const& __rhs) const noexcept { + return __p_ < __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator==(directory_entry const& __rhs) const noexcept { + return __p_ == __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator!=(directory_entry const& __rhs) const noexcept { + return __p_ != __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator<=(directory_entry const& __rhs) const noexcept { + return __p_ <= __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator>(directory_entry const& __rhs) const noexcept { + return __p_ > __rhs.__p_; + } + + _LIBCPP_INLINE_VISIBILITY + bool operator>=(directory_entry const& __rhs) const noexcept { + return __p_ >= __rhs.__p_; + } + +private: + friend class directory_iterator; + friend class recursive_directory_iterator; + friend class __dir_stream; + + enum _CacheType : unsigned char { + _Empty, + _IterSymlink, + _IterNonSymlink, + _RefreshSymlink, + _RefreshSymlinkUnresolved, + _RefreshNonSymlink + }; + + struct __cached_data { + uintmax_t __size_; + uintmax_t __nlink_; + file_time_type __write_time_; + perms __sym_perms_; + perms __non_sym_perms_; + file_type __type_; + _CacheType __cache_type_; + + _LIBCPP_INLINE_VISIBILITY + __cached_data() noexcept { __reset(); } + + _LIBCPP_INLINE_VISIBILITY + void __reset() { + __cache_type_ = _Empty; + __type_ = file_type::none; + __sym_perms_ = __non_sym_perms_ = perms::unknown; + __size_ = __nlink_ = uintmax_t(-1); + __write_time_ = file_time_type::min(); + } + }; + + _LIBCPP_INLINE_VISIBILITY + static __cached_data __create_iter_result(file_type __ft) { + __cached_data __data; + __data.__type_ = __ft; + __data.__cache_type_ = [&]() { + switch (__ft) { + case file_type::none: + return _Empty; + case file_type::symlink: + return _IterSymlink; + default: + return _IterNonSymlink; + } + }(); + return __data; + } + + _LIBCPP_INLINE_VISIBILITY + void __assign_iter_entry(_Path&& __p, __cached_data __dt) { + __p_ = std::move(__p); + __data_ = __dt; + } + + _LIBCPP_FUNC_VIS + error_code __do_refresh() noexcept; + + _LIBCPP_INLINE_VISIBILITY + static bool __is_dne_error(error_code const& __ec) { + if (!__ec) + return true; + switch (static_cast(__ec.value())) { + case errc::no_such_file_or_directory: + case errc::not_a_directory: + return true; + default: + return false; + } + } + + _LIBCPP_INLINE_VISIBILITY + void __handle_error(const char* __msg, error_code* __dest_ec, + error_code const& __ec, bool __allow_dne = false) const { + if (__dest_ec) { + *__dest_ec = __ec; + return; + } + if (__ec && (!__allow_dne || !__is_dne_error(__ec))) + __throw_filesystem_error(__msg, __p_, __ec); + } + + _LIBCPP_INLINE_VISIBILITY + void __refresh(error_code* __ec = nullptr) { + __handle_error("in directory_entry::refresh", __ec, __do_refresh(), + /*allow_dne*/ true); + } + + _LIBCPP_INLINE_VISIBILITY + file_type __get_sym_ft(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + return __symlink_status(__p_, __ec).type(); + case _IterSymlink: + case _RefreshSymlink: + case _RefreshSymlinkUnresolved: + if (__ec) + __ec->clear(); + return file_type::symlink; + case _IterNonSymlink: + case _RefreshNonSymlink: + file_status __st(__data_.__type_); + if (__ec && !_VSTD_FS::exists(__st)) + *__ec = make_error_code(errc::no_such_file_or_directory); + else if (__ec) + __ec->clear(); + return __data_.__type_; + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + file_type __get_ft(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return __status(__p_, __ec).type(); + case _IterNonSymlink: + case _RefreshNonSymlink: + case _RefreshSymlink: { + file_status __st(__data_.__type_); + if (__ec && !_VSTD_FS::exists(__st)) + *__ec = make_error_code(errc::no_such_file_or_directory); + else if (__ec) + __ec->clear(); + return __data_.__type_; + } + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + file_status __get_status(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return __status(__p_, __ec); + case _RefreshNonSymlink: + case _RefreshSymlink: + return file_status(__get_ft(__ec), __data_.__non_sym_perms_); + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + file_status __get_symlink_status(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + return __symlink_status(__p_, __ec); + case _RefreshNonSymlink: + return file_status(__get_sym_ft(__ec), __data_.__non_sym_perms_); + case _RefreshSymlink: + case _RefreshSymlinkUnresolved: + return file_status(__get_sym_ft(__ec), __data_.__sym_perms_); + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t __get_size(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__file_size(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + file_status __st(__get_ft(&__m_ec)); + __handle_error("in directory_entry::file_size", __ec, __m_ec); + if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) { + errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory + : errc::not_supported; + __handle_error("in directory_entry::file_size", __ec, + make_error_code(__err_kind)); + } + return __data_.__size_; + } + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + uintmax_t __get_nlink(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__hard_link_count(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + (void)__get_ft(&__m_ec); + __handle_error("in directory_entry::hard_link_count", __ec, __m_ec); + return __data_.__nlink_; + } + } + _LIBCPP_UNREACHABLE(); + } + + _LIBCPP_INLINE_VISIBILITY + file_time_type __get_write_time(error_code* __ec = nullptr) const { + switch (__data_.__cache_type_) { + case _Empty: + case _IterNonSymlink: + case _IterSymlink: + case _RefreshSymlinkUnresolved: + return _VSTD_FS::__last_write_time(__p_, __ec); + case _RefreshSymlink: + case _RefreshNonSymlink: { + error_code __m_ec; + file_status __st(__get_ft(&__m_ec)); + __handle_error("in directory_entry::last_write_time", __ec, __m_ec); + if (_VSTD_FS::exists(__st) && + __data_.__write_time_ == file_time_type::min()) + __handle_error("in directory_entry::last_write_time", __ec, + make_error_code(errc::value_too_large)); + return __data_.__write_time_; + } + } + _LIBCPP_UNREACHABLE(); + } + +private: + _Path __p_; + __cached_data __data_; +}; + +class __dir_element_proxy { +public: + inline _LIBCPP_INLINE_VISIBILITY directory_entry operator*() { + return _VSTD::move(__elem_); + } + +private: + friend class directory_iterator; + friend class recursive_directory_iterator; + explicit __dir_element_proxy(directory_entry const& __e) : __elem_(__e) {} + __dir_element_proxy(__dir_element_proxy&& __o) + : __elem_(_VSTD::move(__o.__elem_)) {} + directory_entry __elem_; +}; + +class directory_iterator { +public: + typedef directory_entry value_type; + typedef ptrdiff_t difference_type; + typedef value_type const* pointer; + typedef value_type const& reference; + typedef input_iterator_tag iterator_category; + +public: + //ctor & dtor + directory_iterator() noexcept {} + + explicit directory_iterator(const path& __p) + : directory_iterator(__p, nullptr) {} + + directory_iterator(const path& __p, directory_options __opts) + : directory_iterator(__p, nullptr, __opts) {} + + directory_iterator(const path& __p, error_code& __ec) + : directory_iterator(__p, &__ec) {} + + directory_iterator(const path& __p, directory_options __opts, + error_code& __ec) + : directory_iterator(__p, &__ec, __opts) {} + + directory_iterator(const directory_iterator&) = default; + directory_iterator(directory_iterator&&) = default; + directory_iterator& operator=(const directory_iterator&) = default; + + directory_iterator& operator=(directory_iterator&& __o) noexcept { + // non-default implementation provided to support self-move assign. + if (this != &__o) { + __imp_ = _VSTD::move(__o.__imp_); + } + return *this; + } + + ~directory_iterator() = default; + + const directory_entry& operator*() const { + _LIBCPP_ASSERT(__imp_, "The end iterator cannot be dereferenced"); + return __dereference(); + } + + const directory_entry* operator->() const { return &**this; } + + directory_iterator& operator++() { return __increment(); } + + __dir_element_proxy operator++(int) { + __dir_element_proxy __p(**this); + __increment(); + return __p; + } + + directory_iterator& increment(error_code& __ec) { return __increment(&__ec); } + +private: + inline _LIBCPP_INLINE_VISIBILITY friend bool + operator==(const directory_iterator& __lhs, + const directory_iterator& __rhs) noexcept; + + // construct the dir_stream + _LIBCPP_FUNC_VIS + directory_iterator(const path&, error_code*, + directory_options = directory_options::none); + + _LIBCPP_FUNC_VIS + directory_iterator& __increment(error_code* __ec = nullptr); + + _LIBCPP_FUNC_VIS + const directory_entry& __dereference() const; + +private: + shared_ptr<__dir_stream> __imp_; +}; + +inline _LIBCPP_INLINE_VISIBILITY bool +operator==(const directory_iterator& __lhs, + const directory_iterator& __rhs) noexcept { + return __lhs.__imp_ == __rhs.__imp_; +} + +inline _LIBCPP_INLINE_VISIBILITY bool +operator!=(const directory_iterator& __lhs, + const directory_iterator& __rhs) noexcept { + return !(__lhs == __rhs); +} + +// enable directory_iterator range-based for statements +inline _LIBCPP_INLINE_VISIBILITY directory_iterator +begin(directory_iterator __iter) noexcept { + return __iter; +} + +inline _LIBCPP_INLINE_VISIBILITY directory_iterator +end(const directory_iterator&) noexcept { + return directory_iterator(); +} + +class recursive_directory_iterator { +public: + using value_type = directory_entry; + using difference_type = std::ptrdiff_t; + using pointer = directory_entry const*; + using reference = directory_entry const&; + using iterator_category = std::input_iterator_tag; + +public: + // constructors and destructor + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator() noexcept : __rec_(false) {} + + _LIBCPP_INLINE_VISIBILITY + explicit recursive_directory_iterator( + const path& __p, directory_options __xoptions = directory_options::none) + : recursive_directory_iterator(__p, __xoptions, nullptr) {} + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator(const path& __p, directory_options __xoptions, + error_code& __ec) + : recursive_directory_iterator(__p, __xoptions, &__ec) {} + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator(const path& __p, error_code& __ec) + : recursive_directory_iterator(__p, directory_options::none, &__ec) {} + + recursive_directory_iterator(const recursive_directory_iterator&) = default; + recursive_directory_iterator(recursive_directory_iterator&&) = default; + + recursive_directory_iterator& + operator=(const recursive_directory_iterator&) = default; + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator& + operator=(recursive_directory_iterator&& __o) noexcept { + // non-default implementation provided to support self-move assign. + if (this != &__o) { + __imp_ = _VSTD::move(__o.__imp_); + __rec_ = __o.__rec_; + } + return *this; + } + + ~recursive_directory_iterator() = default; + + _LIBCPP_INLINE_VISIBILITY + const directory_entry& operator*() const { return __dereference(); } + + _LIBCPP_INLINE_VISIBILITY + const directory_entry* operator->() const { return &__dereference(); } + + recursive_directory_iterator& operator++() { return __increment(); } + + _LIBCPP_INLINE_VISIBILITY + __dir_element_proxy operator++(int) { + __dir_element_proxy __p(**this); + __increment(); + return __p; + } + + _LIBCPP_INLINE_VISIBILITY + recursive_directory_iterator& increment(error_code& __ec) { + return __increment(&__ec); + } + + _LIBCPP_FUNC_VIS directory_options options() const; + _LIBCPP_FUNC_VIS int depth() const; + + _LIBCPP_INLINE_VISIBILITY + void pop() { __pop(); } + + _LIBCPP_INLINE_VISIBILITY + void pop(error_code& __ec) { __pop(&__ec); } + + _LIBCPP_INLINE_VISIBILITY + bool recursion_pending() const { return __rec_; } + + _LIBCPP_INLINE_VISIBILITY + void disable_recursion_pending() { __rec_ = false; } + +private: + recursive_directory_iterator(const path& __p, directory_options __opt, + error_code* __ec); + + _LIBCPP_FUNC_VIS + const directory_entry& __dereference() const; + + _LIBCPP_FUNC_VIS + bool __try_recursion(error_code* __ec); + + _LIBCPP_FUNC_VIS + void __advance(error_code* __ec = nullptr); + + _LIBCPP_FUNC_VIS + recursive_directory_iterator& __increment(error_code* __ec = nullptr); + + _LIBCPP_FUNC_VIS + void __pop(error_code* __ec = nullptr); + + inline _LIBCPP_INLINE_VISIBILITY friend bool + operator==(const recursive_directory_iterator&, + const recursive_directory_iterator&) noexcept; + + struct __shared_imp; + shared_ptr<__shared_imp> __imp_; + bool __rec_; +}; // class recursive_directory_iterator + +inline _LIBCPP_INLINE_VISIBILITY bool +operator==(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) noexcept { + return __lhs.__imp_ == __rhs.__imp_; +} + +_LIBCPP_INLINE_VISIBILITY +inline bool operator!=(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) noexcept { + return !(__lhs == __rhs); +} +// enable recursive_directory_iterator range-based for statements +inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator +begin(recursive_directory_iterator __iter) noexcept { + return __iter; +} + +inline _LIBCPP_INLINE_VISIBILITY recursive_directory_iterator +end(const recursive_directory_iterator&) noexcept { + return recursive_directory_iterator(); +} + +_LIBCPP_END_NAMESPACE_FILESYSTEM + +#endif // !_LIBCPP_CXX03_LANG + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_FILESYSTEM diff --git a/include/fstream b/include/fstream index 8b9aefaac..332b4747c 100644 --- a/include/fstream +++ b/include/fstream @@ -38,6 +38,7 @@ public: bool is_open() const; basic_filebuf* open(const char* s, ios_base::openmode mode); basic_filebuf* open(const string& s, ios_base::openmode mode); + basic_filebuf* open(const filesystem::path& p, ios_base::openmode mode); // C++17 basic_filebuf* close(); protected: @@ -77,6 +78,8 @@ public: basic_ifstream(); explicit basic_ifstream(const char* s, ios_base::openmode mode = ios_base::in); explicit basic_ifstream(const string& s, ios_base::openmode mode = ios_base::in); + explicit basic_ifstream(const filesystem::path& p, + ios_base::openmode mode = ios_base::in); // C++17 basic_ifstream(basic_ifstream&& rhs); basic_ifstream& operator=(basic_ifstream&& rhs); @@ -86,6 +89,8 @@ public: bool is_open() const; void open(const char* s, ios_base::openmode mode = ios_base::in); void open(const string& s, ios_base::openmode mode = ios_base::in); + void open(const filesystem::path& s, ios_base::openmode mode = ios_base::in); // C++17 + void close(); }; @@ -110,6 +115,8 @@ public: basic_ofstream(); explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out); explicit basic_ofstream(const string& s, ios_base::openmode mode = ios_base::out); + explicit basic_ofstream(const filesystem::path& p, + ios_base::openmode mode = ios_base::out); // C++17 basic_ofstream(basic_ofstream&& rhs); basic_ofstream& operator=(basic_ofstream&& rhs); @@ -119,6 +126,9 @@ public: bool is_open() const; void open(const char* s, ios_base::openmode mode = ios_base::out); void open(const string& s, ios_base::openmode mode = ios_base::out); + void open(const filesystem::path& p, + ios_base::openmode mode = ios_base::out); // C++17 + void close(); }; @@ -143,6 +153,8 @@ public: basic_fstream(); explicit basic_fstream(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out); explicit basic_fstream(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out); + explicit basic_fstream(const filesystem::path& p, + ios_base::openmode mode = ios_base::in|ios_base::out); C++17 basic_fstream(basic_fstream&& rhs); basic_fstream& operator=(basic_fstream&& rhs); @@ -152,6 +164,9 @@ public: bool is_open() const; void open(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out); void open(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out); + void open(const filesystem::path& s, + ios_base::openmode mode = ios_base::in|ios_base::out); // C++17 + void close(); }; @@ -171,6 +186,7 @@ typedef basic_fstream wfstream; #include <__locale> #include #include +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header @@ -219,6 +235,12 @@ public: _LIBCPP_INLINE_VISIBILITY basic_filebuf* open(const string& __s, ios_base::openmode __mode); +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_INLINE_VISIBILITY + basic_filebuf* open(const _VSTD_FS::path& __p, ios_base::openmode __mode) { + return open(__p.c_str(), __mode); + } +#endif _LIBCPP_INLINE_VISIBILITY basic_filebuf* __open(int __fd, ios_base::openmode __mode); #endif @@ -1128,6 +1150,11 @@ public: #endif _LIBCPP_INLINE_VISIBILITY explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in); +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_INLINE_VISIBILITY + explicit basic_ifstream(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in) + : basic_ifstream(__p.c_str(), __mode) {} +#endif // _LIBCPP_STD_VER >= 17 #endif #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY @@ -1149,6 +1176,13 @@ public: void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in); #endif void open(const string& __s, ios_base::openmode __mode = ios_base::in); +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_INLINE_VISIBILITY + void open(const filesystem::path& __p, + ios_base::openmode __mode = ios_base::in) { + return open(__p.c_str(), __mode); + } +#endif // _LIBCPP_STD_VER >= 17 _LIBCPP_INLINE_VISIBILITY void __open(int __fd, ios_base::openmode __mode); @@ -1329,6 +1363,13 @@ public: #endif _LIBCPP_INLINE_VISIBILITY explicit basic_ofstream(const string& __s, ios_base::openmode __mode = ios_base::out); + +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_INLINE_VISIBILITY + explicit basic_ofstream(const filesystem::path& __p, ios_base::openmode __mode = ios_base::out) + : basic_ofstream(__p.c_str(), __mode) {} +#endif // _LIBCPP_STD_VER >= 17 + #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_ofstream(basic_ofstream&& __rhs); @@ -1350,6 +1391,12 @@ public: #endif void open(const string& __s, ios_base::openmode __mode = ios_base::out); +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_INLINE_VISIBILITY + void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::out) + { return open(__p.c_str(), __mode); } +#endif // _LIBCPP_STD_VER >= 17 + _LIBCPP_INLINE_VISIBILITY void __open(int __fd, ios_base::openmode __mode); #endif @@ -1530,6 +1577,13 @@ public: #endif _LIBCPP_INLINE_VISIBILITY explicit basic_fstream(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out); + +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_INLINE_VISIBILITY + explicit basic_fstream(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in | ios_base::out) + : basic_fstream(__p.c_str(), __mode) {} +#endif // _LIBCPP_STD_VER >= 17 + #endif #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY @@ -1551,6 +1605,13 @@ public: void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); #endif void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out); + +#if _LIBCPP_STD_VER >= 17 + _LIBCPP_INLINE_VISIBILITY + void open(const filesystem::path& __p, ios_base::openmode __mode = ios_base::in|ios_base::out) + { return open(__p.c_str(), __mode); } +#endif // _LIBCPP_STD_VER >= 17 + #endif _LIBCPP_INLINE_VISIBILITY void close(); diff --git a/include/module.modulemap b/include/module.modulemap index e17c3a2f6..127a42b06 100644 --- a/include/module.modulemap +++ b/include/module.modulemap @@ -264,6 +264,10 @@ module std [system] { header "exception" export * } + module filesystem { + header "filesystem" + export * + } module forward_list { header "forward_list" export initializer_list diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 5cdf1b868..a40d217dc 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -291,12 +291,43 @@ endif() # Add a meta-target for both libraries. add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_BUILD_TARGETS}) + +if (LIBCXX_ENABLE_FILESYSTEM) + set(LIBCXX_FILESYSTEM_SOURCES + ../src/filesystem/operations.cpp + ../src/filesystem/directory_iterator.cpp) + + # Filesystem uses __int128_t, which requires a definition of __muloi4 when + # compiled with UBSAN. This definition is not provided by libgcc_s, but is + # provided by compiler-rt. So we need to disable it to avoid having multiple + # definitions. See filesystem/int128_builtins.cpp. + if (NOT LIBCXX_USE_COMPILER_RT) + list(APPEND LIBCXX_FILESYSTEM_SOURCES ../src/filesystem/int128_builtins.cpp) + endif() + + add_library(cxx_filesystem STATIC ${LIBCXX_FILESYSTEM_SOURCES}) + if (LIBCXX_ENABLE_SHARED) + target_link_libraries(cxx_filesystem cxx_shared) + else() + target_link_libraries(cxx_filesystem cxx_static) + endif() + + set(filesystem_flags "${LIBCXX_COMPILE_FLAGS}") + check_flag_supported(-std=c++14) + if (NOT MSVC AND LIBCXX_SUPPORTS_STD_EQ_CXX14_FLAG) + string(REPLACE "-std=c++11" "-std=c++14" filesystem_flags "${LIBCXX_COMPILE_FLAGS}") + endif() + set_target_properties(cxx_filesystem + PROPERTIES + COMPILE_FLAGS "${filesystem_flags}" + OUTPUT_NAME "c++fs" + ) +endif() + + if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) file(GLOB LIBCXX_EXPERIMENTAL_SOURCES ../src/experimental/*.cpp) - if (LIBCXX_ENABLE_FILESYSTEM) - file(GLOB LIBCXX_FILESYSTEM_SOURCES ../src/experimental/filesystem/*.cpp) - endif() - add_library(cxx_experimental STATIC ${LIBCXX_EXPERIMENTAL_SOURCES} ${LIBCXX_FILESYSTEM_SOURCES}) + add_library(cxx_experimental STATIC ${LIBCXX_EXPERIMENTAL_SOURCES}) if (LIBCXX_ENABLE_SHARED) target_link_libraries(cxx_experimental cxx_shared) else() @@ -315,6 +346,7 @@ if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) ) endif() + if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY) file(GLOB LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES ../test/support/external_threads.cpp) @@ -362,10 +394,13 @@ if (LIBCXX_ENABLE_SHARED AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT) endif() if (LIBCXX_INSTALL_LIBRARY) + if (LIBCXX_INSTALL_FILESYSTEM_LIBRARY) + set(filesystem_lib cxx_filesystem) + endif() if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY) set(experimental_lib cxx_experimental) endif() - install(TARGETS ${LIBCXX_INSTALL_TARGETS} ${experimental_lib} + install(TARGETS ${LIBCXX_INSTALL_TARGETS} ${filesystem_lib} ${experimental_lib} LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}lib${LIBCXX_LIBDIR_SUFFIX} COMPONENT cxx ) @@ -385,6 +420,9 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR if(LIBCXX_INSTALL_LIBRARY) set(lib_install_target cxx) endif() + if (LIBCXX_INSTALL_FILESYSTEM_LIBRARY) + set(filesystem_lib_install_target cxx_filesystem) + endif() if (LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY) set(experimental_lib_install_target cxx_experimental) endif() @@ -394,6 +432,7 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR add_custom_target(install-cxx DEPENDS ${lib_install_target} ${experimental_lib_install_target} + ${filesystem_lib_install_target} ${header_install_target} COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cxx @@ -401,6 +440,7 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND (LIBCXX_INSTALL_LIBRARY OR add_custom_target(install-cxx-stripped DEPENDS ${lib_install_target} ${experimental_lib_install_target} + ${filesystem_lib_install_target} ${header_install_target} COMMAND "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=cxx diff --git a/src/experimental/filesystem/directory_iterator.cpp b/src/filesystem/directory_iterator.cpp similarity index 55% rename from src/experimental/filesystem/directory_iterator.cpp rename to src/filesystem/directory_iterator.cpp index 7a1ab2573..f0d807a03 100644 --- a/src/experimental/filesystem/directory_iterator.cpp +++ b/src/filesystem/directory_iterator.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "experimental/filesystem" +#include "filesystem" #include "__config" #if defined(_LIBCPP_WIN32API) #define WIN32_LEAN_AND_MEAN @@ -19,14 +19,14 @@ #include "filesystem_common.h" -_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM namespace detail { namespace { #if !defined(_LIBCPP_WIN32API) template -static file_type get_file_type(DirEntT *ent, int) { +static file_type get_file_type(DirEntT* ent, int) { switch (ent->d_type) { case DT_BLK: return file_type::block; @@ -52,22 +52,22 @@ static file_type get_file_type(DirEntT *ent, int) { } template -static file_type get_file_type(DirEntT *ent, long) { +static file_type get_file_type(DirEntT* ent, long) { return file_type::none; } -static pair -posix_readdir(DIR *dir_stream, error_code& ec) { - struct dirent* dir_entry_ptr = nullptr; - errno = 0; // zero errno in order to detect errors - ec.clear(); - if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) { - if (errno) - ec = capture_errno(); - return {}; - } else { - return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)}; - } +static pair posix_readdir(DIR* dir_stream, + error_code& ec) { + struct dirent* dir_entry_ptr = nullptr; + errno = 0; // zero errno in order to detect errors + ec.clear(); + if ((dir_entry_ptr = ::readdir(dir_stream)) == nullptr) { + if (errno) + ec = capture_errno(); + return {}; + } else { + return {dir_entry_ptr->d_name, get_file_type(dir_entry_ptr, 0)}; + } } #else @@ -77,7 +77,7 @@ static file_type get_file_type(const WIN32_FIND_DATA& data) { return file_type::unknown; } static uintmax_t get_file_size(const WIN32_FIND_DATA& data) { - return (data.nFileSizeHight * (MAXDWORD+1)) + data.nFileSizeLow; + return (data.nFileSizeHight * (MAXDWORD + 1)) + data.nFileSizeLow; } static file_time_type get_write_time(const WIN32_FIND_DATA& data) { ULARGE_INTEGER tmp; @@ -97,19 +97,18 @@ using detail::ErrorHandler; #if defined(_LIBCPP_WIN32API) class __dir_stream { public: - __dir_stream() = delete; __dir_stream& operator=(const __dir_stream&) = delete; - __dir_stream(__dir_stream&& __ds) noexcept - : __stream_(__ds.__stream_), __root_(move(__ds.__root_)), - __entry_(move(__ds.__entry_)) { + __dir_stream(__dir_stream&& __ds) noexcept : __stream_(__ds.__stream_), + __root_(move(__ds.__root_)), + __entry_(move(__ds.__entry_)) { __ds.__stream_ = INVALID_HANDLE_VALUE; } __dir_stream(const path& root, directory_options opts, error_code& ec) : __stream_(INVALID_HANDLE_VALUE), __root_(root) { - __stream_ = ::FindFirstFileEx(root.c_str(), &__data_); + __stream_ = ::FindFirstFileEx(root.c_str(), &__data_); if (__stream_ == INVALID_HANDLE_VALUE) { ec = error_code(::GetLastError(), generic_category()); const bool ignore_permission_denied = @@ -166,75 +165,74 @@ public: #else class __dir_stream { public: - __dir_stream() = delete; - __dir_stream& operator=(const __dir_stream&) = delete; - - __dir_stream(__dir_stream&& other) noexcept - : __stream_(other.__stream_), __root_(move(other.__root_)), - __entry_(move(other.__entry_)) - { - other.__stream_ = nullptr; - } + __dir_stream() = delete; + __dir_stream& operator=(const __dir_stream&) = delete; + __dir_stream(__dir_stream&& other) noexcept : __stream_(other.__stream_), + __root_(move(other.__root_)), + __entry_(move(other.__entry_)) { + other.__stream_ = nullptr; + } - __dir_stream(const path& root, directory_options opts, error_code& ec) - : __stream_(nullptr), - __root_(root) - { - if ((__stream_ = ::opendir(root.c_str())) == nullptr) { - ec = detail::capture_errno(); - const bool allow_eacess = - bool(opts & directory_options::skip_permission_denied); - if (allow_eacess && ec.value() == EACCES) - ec.clear(); - return; - } - advance(ec); + __dir_stream(const path& root, directory_options opts, error_code& ec) + : __stream_(nullptr), __root_(root) { + if ((__stream_ = ::opendir(root.c_str())) == nullptr) { + ec = detail::capture_errno(); + const bool allow_eacess = + bool(opts & directory_options::skip_permission_denied); + if (allow_eacess && ec.value() == EACCES) + ec.clear(); + return; } + advance(ec); + } - ~__dir_stream() noexcept - { if (__stream_) close(); } - - bool good() const noexcept { return __stream_ != nullptr; } - - bool advance(error_code &ec) { - while (true) { - auto str_type_pair = detail::posix_readdir(__stream_, ec); - auto& str = str_type_pair.first; - if (str == "." || str == "..") { - continue; - } else if (ec || str.empty()) { - close(); - return false; - } else { - __entry_.__assign_iter_entry( - __root_ / str, - directory_entry::__create_iter_result(str_type_pair.second)); - return true; - } - } + ~__dir_stream() noexcept { + if (__stream_) + close(); + } + + bool good() const noexcept { return __stream_ != nullptr; } + + bool advance(error_code& ec) { + while (true) { + auto str_type_pair = detail::posix_readdir(__stream_, ec); + auto& str = str_type_pair.first; + if (str == "." || str == "..") { + continue; + } else if (ec || str.empty()) { + close(); + return false; + } else { + __entry_.__assign_iter_entry( + __root_ / str, + directory_entry::__create_iter_result(str_type_pair.second)); + return true; + } } + } + private: - error_code close() noexcept { - error_code m_ec; - if (::closedir(__stream_) == -1) - m_ec = detail::capture_errno(); - __stream_ = nullptr; - return m_ec; - } + error_code close() noexcept { + error_code m_ec; + if (::closedir(__stream_) == -1) + m_ec = detail::capture_errno(); + __stream_ = nullptr; + return m_ec; + } + + DIR* __stream_{nullptr}; - DIR * __stream_{nullptr}; public: - path __root_; - directory_entry __entry_; + path __root_; + directory_entry __entry_; }; #endif // directory_iterator -directory_iterator::directory_iterator(const path& p, error_code *ec, - directory_options opts) -{ +directory_iterator::directory_iterator(const path& p, error_code* ec, + directory_options opts) { ErrorHandler err("directory_iterator::directory_iterator(...)", ec, &p); error_code m_ec; @@ -248,38 +246,35 @@ directory_iterator::directory_iterator(const path& p, error_code *ec, } } -directory_iterator& directory_iterator::__increment(error_code *ec) -{ - _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator"); - ErrorHandler err("directory_iterator::operator++()", ec); - - error_code m_ec; - if (!__imp_->advance(m_ec)) { - path root = move(__imp_->__root_); - __imp_.reset(); - if (m_ec) - err.report(m_ec, "at root \"%s\"", root); - } - return *this; +directory_iterator& directory_iterator::__increment(error_code* ec) { + _LIBCPP_ASSERT(__imp_, "Attempting to increment an invalid iterator"); + ErrorHandler err("directory_iterator::operator++()", ec); + error_code m_ec; + if (!__imp_->advance(m_ec)) { + path root = move(__imp_->__root_); + __imp_.reset(); + if (m_ec) + err.report(m_ec, "at root \"%s\"", root); + } + return *this; } directory_entry const& directory_iterator::__dereference() const { - _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator"); - return __imp_->__entry_; + _LIBCPP_ASSERT(__imp_, "Attempting to dereference an invalid iterator"); + return __imp_->__entry_; } // recursive_directory_iterator struct recursive_directory_iterator::__shared_imp { stack<__dir_stream> __stack_; - directory_options __options_; + directory_options __options_; }; -recursive_directory_iterator::recursive_directory_iterator(const path& p, - directory_options opt, error_code *ec) - : __imp_(nullptr), __rec_(true) -{ +recursive_directory_iterator::recursive_directory_iterator( + const path& p, directory_options opt, error_code* ec) + : __imp_(nullptr), __rec_(true) { ErrorHandler err("recursive_directory_iterator", ec, &p); error_code m_ec; @@ -294,40 +289,40 @@ recursive_directory_iterator::recursive_directory_iterator(const path& p, __imp_->__stack_.push(move(new_s)); } -void recursive_directory_iterator::__pop(error_code* ec) -{ - _LIBCPP_ASSERT(__imp_, "Popping the end iterator"); - if (ec) ec->clear(); - __imp_->__stack_.pop(); - if (__imp_->__stack_.size() == 0) - __imp_.reset(); - else - __advance(ec); +void recursive_directory_iterator::__pop(error_code* ec) { + _LIBCPP_ASSERT(__imp_, "Popping the end iterator"); + if (ec) + ec->clear(); + __imp_->__stack_.pop(); + if (__imp_->__stack_.size() == 0) + __imp_.reset(); + else + __advance(ec); } directory_options recursive_directory_iterator::options() const { - return __imp_->__options_; + return __imp_->__options_; } int recursive_directory_iterator::depth() const { - return __imp_->__stack_.size() - 1; + return __imp_->__stack_.size() - 1; } const directory_entry& recursive_directory_iterator::__dereference() const { - return __imp_->__stack_.top().__entry_; + return __imp_->__stack_.top().__entry_; } recursive_directory_iterator& -recursive_directory_iterator::__increment(error_code *ec) -{ - if (ec) ec->clear(); - if (recursion_pending()) { - if (__try_recursion(ec) || (ec && *ec)) - return *this; - } - __rec_ = true; - __advance(ec); - return *this; +recursive_directory_iterator::__increment(error_code* ec) { + if (ec) + ec->clear(); + if (recursion_pending()) { + if (__try_recursion(ec) || (ec && *ec)) + return *this; + } + __rec_ = true; + __advance(ec); + return *this; } void recursive_directory_iterator::__advance(error_code* ec) { @@ -344,16 +339,16 @@ void recursive_directory_iterator::__advance(error_code* ec) { stack.pop(); } - if (m_ec) { - path root = move(stack.top().__root_); - __imp_.reset(); - err.report(m_ec, "at root \"%s\"", root); - } else { - __imp_.reset(); - } + if (m_ec) { + path root = move(stack.top().__root_); + __imp_.reset(); + err.report(m_ec, "at root \"%s\"", root); + } else { + __imp_.reset(); + } } -bool recursive_directory_iterator::__try_recursion(error_code *ec) { +bool recursive_directory_iterator::__try_recursion(error_code* ec) { ErrorHandler err("recursive_directory_iterator::operator++()", ec); bool rec_sym = bool(options() & directory_options::follow_directory_symlink); @@ -376,26 +371,26 @@ bool recursive_directory_iterator::__try_recursion(error_code *ec) { skip_rec = true; } - if (!skip_rec) { - __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec); - if (new_it.good()) { - __imp_->__stack_.push(move(new_it)); - return true; - } + if (!skip_rec) { + __dir_stream new_it(curr_it.__entry_.path(), __imp_->__options_, m_ec); + if (new_it.good()) { + __imp_->__stack_.push(move(new_it)); + return true; } - if (m_ec) { - const bool allow_eacess = bool(__imp_->__options_ - & directory_options::skip_permission_denied); - if (m_ec.value() == EACCES && allow_eacess) { - if (ec) ec->clear(); - } else { - path at_ent = move(curr_it.__entry_.__p_); - __imp_.reset(); - err.report(m_ec, "attempting recursion into \"%s\"", at_ent); - } + } + if (m_ec) { + const bool allow_eacess = + bool(__imp_->__options_ & directory_options::skip_permission_denied); + if (m_ec.value() == EACCES && allow_eacess) { + if (ec) + ec->clear(); + } else { + path at_ent = move(curr_it.__entry_.__p_); + __imp_.reset(); + err.report(m_ec, "attempting recursion into \"%s\"", at_ent); } - return false; + } + return false; } - -_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM +_LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/src/experimental/filesystem/filesystem_common.h b/src/filesystem/filesystem_common.h similarity index 96% rename from src/experimental/filesystem/filesystem_common.h rename to src/filesystem/filesystem_common.h index 94f4d41cc..ed92877c4 100644 --- a/src/experimental/filesystem/filesystem_common.h +++ b/src/filesystem/filesystem_common.h @@ -10,7 +10,8 @@ #ifndef FILESYSTEM_COMMON_H #define FILESYSTEM_COMMON_H -#include "experimental/__config" +#include "__config" +#include "filesystem" #include "array" #include "chrono" #include "cstdlib" @@ -20,11 +21,9 @@ #include #include #include // for ::utimes as used in __last_write_time -#include /* values for fchmodat */ +#include /* values for fchmodat */ -#include - -#include "../../include/apple_availability.h" +#include "../include/apple_availability.h" #if !defined(__APPLE__) // We can use the presence of UTIME_OMIT to detect platforms that provide @@ -39,7 +38,7 @@ #pragma GCC diagnostic ignored "-Wunused-function" #endif -_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM namespace detail { namespace { @@ -49,7 +48,7 @@ static string format_string_imp(const char* msg, ...) { struct GuardVAList { va_list& target; bool active = true; - GuardVAList(va_list &target) : target(target), active(true) {} + GuardVAList(va_list& target) : target(target), active(true) {} void clear() { if (active) va_end(target); @@ -386,10 +385,10 @@ TimeSpec extract_atime(StatT const& st) { return st.st_atim; } // to use it. bool posix_utimes(const path& p, std::array const& TS, - error_code& ec) { + error_code& ec) { using namespace chrono; auto Convert = [](long nsec) { - using int_type = decltype(std::declval<::timeval>().tv_usec); + using int_type = decltype(std::declval< ::timeval>().tv_usec); auto dur = duration_cast(nanoseconds(nsec)).count(); return static_cast(dur); }; @@ -404,9 +403,8 @@ bool posix_utimes(const path& p, std::array const& TS, #if defined(_LIBCPP_USE_UTIMENSAT) bool posix_utimensat(const path& p, std::array const& TS, - error_code& ec) { - if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) - { + error_code& ec) { + if (::utimensat(AT_FDCWD, p.c_str(), TS.data(), 0) == -1) { ec = capture_errno(); return true; } @@ -423,10 +421,9 @@ bool set_file_times(const path& p, std::array const& TS, #endif } - } // namespace } // end namespace detail -_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM +_LIBCPP_END_NAMESPACE_FILESYSTEM #endif // FILESYSTEM_COMMON_H diff --git a/src/experimental/filesystem/int128_builtins.cpp b/src/filesystem/int128_builtins.cpp similarity index 97% rename from src/experimental/filesystem/int128_builtins.cpp rename to src/filesystem/int128_builtins.cpp index d8f2abbf9..66adbdd2d 100644 --- a/src/experimental/filesystem/int128_builtins.cpp +++ b/src/filesystem/int128_builtins.cpp @@ -17,7 +17,7 @@ #include "__config" #include "climits" -#ifndef _LIBCPP_HAS_NO_INT128 +#if !defined(_LIBCPP_HAS_NO_INT128) extern "C" __attribute__((no_sanitize("undefined"))) __int128_t __muloti4(__int128_t a, __int128_t b, int* overflow) { diff --git a/src/experimental/filesystem/operations.cpp b/src/filesystem/operations.cpp similarity index 76% rename from src/experimental/filesystem/operations.cpp rename to src/filesystem/operations.cpp index 775c178b3..65a4b3193 100644 --- a/src/experimental/filesystem/operations.cpp +++ b/src/filesystem/operations.cpp @@ -7,11 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "experimental/filesystem" +#include "filesystem" #include "array" #include "iterator" #include "fstream" -#include "random" /* for unique_path */ +#include "random" /* for unique_path */ #include "string_view" #include "type_traits" #include "vector" @@ -24,17 +24,17 @@ #include #include #include -#include /* values for fchmodat */ +#include /* values for fchmodat */ #if defined(__linux__) -# include -# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) -# include -# define _LIBCPP_USE_SENDFILE -# endif +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) +#include +#define _LIBCPP_USE_SENDFILE +#endif #elif defined(__APPLE__) || __has_include() #include -# define _LIBCPP_USE_COPYFILE +#define _LIBCPP_USE_COPYFILE #endif #if !defined(__APPLE__) @@ -51,10 +51,10 @@ #endif #endif -_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_FILESYSTEM +_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM -namespace { namespace parser -{ +namespace { +namespace parser { using string_view_t = path::__string_view; using string_view_pair = pair; @@ -76,8 +76,8 @@ struct PathParser { ParserState State; private: - PathParser(string_view_t P, ParserState State) noexcept - : Path(P), State(State) {} + PathParser(string_view_t P, ParserState State) noexcept : Path(P), + State(State) {} public: PathParser(string_view_t P, string_view_t E, unsigned char S) @@ -157,7 +157,8 @@ public: } } case PS_InTrailingSep: - return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1, RStart + 1); + return makeState(PS_InFilenames, consumeName(RStart, REnd) + 1, + RStart + 1); case PS_InFilenames: { PosPtr SepEnd = consumeSeparator(RStart, REnd); if (SepEnd == REnd) @@ -219,13 +220,9 @@ private: RawEntry = {}; } - PosPtr getAfterBack() const noexcept { - return Path.data() + Path.size(); - } + PosPtr getAfterBack() const noexcept { return Path.data() + Path.size(); } - PosPtr getBeforeFront() const noexcept { - return Path.data() - 1; - } + PosPtr getBeforeFront() const noexcept { return Path.data() - 1; } /// \brief Return a pointer to the first character after the currently /// lexed element. @@ -282,24 +279,26 @@ private: } }; -string_view_pair separate_filename(string_view_t const & s) { - if (s == "." || s == ".." || s.empty()) return string_view_pair{s, ""}; - auto pos = s.find_last_of('.'); - if (pos == string_view_t::npos || pos == 0) - return string_view_pair{s, string_view_t{}}; - return string_view_pair{s.substr(0, pos), s.substr(pos)}; +string_view_pair separate_filename(string_view_t const& s) { + if (s == "." || s == ".." || s.empty()) + return string_view_pair{s, ""}; + auto pos = s.find_last_of('.'); + if (pos == string_view_t::npos || pos == 0) + return string_view_pair{s, string_view_t{}}; + return string_view_pair{s.substr(0, pos), s.substr(pos)}; } string_view_t createView(PosPtr S, PosPtr E) noexcept { return {S, static_cast(E - S) + 1}; } -}} // namespace parser - +} // namespace parser +} // namespace // POSIX HELPERS -namespace detail { namespace { +namespace detail { +namespace { using value_type = path::value_type; using string_type = path::string_type; @@ -429,8 +428,7 @@ 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) { +bool posix_ftruncate(const FileDescriptor& fd, size_t to_size, error_code& ec) { if (::ftruncate(fd.fd, to_size) == -1) { ec = capture_errno(); return true; @@ -462,7 +460,8 @@ file_status FileDescriptor::refresh_status(error_code& ec) { m_status = create_file_status(m_ec, name, m_stat, &ec); return m_status; } -}} // end namespace detail +} // namespace +} // end namespace detail using detail::capture_errno; using detail::ErrorHandler; @@ -511,37 +510,36 @@ void filesystem_error::__create_what(int __num_paths) { }(); } -static path __do_absolute(const path& p, path *cwd, error_code *ec) { - if (ec) ec->clear(); - if (p.is_absolute()) - return p; - *cwd = __current_path(ec); - if (ec && *ec) - return {}; - return (*cwd) / p; +static path __do_absolute(const path& p, path* cwd, error_code* ec) { + if (ec) + ec->clear(); + if (p.is_absolute()) + return p; + *cwd = __current_path(ec); + if (ec && *ec) + return {}; + return (*cwd) / p; } -path __absolute(const path& p, error_code *ec) { - path cwd; - return __do_absolute(p, &cwd, ec); +path __absolute(const path& p, error_code* ec) { + path cwd; + return __do_absolute(p, &cwd, ec); } -path __canonical(path const & orig_p, error_code *ec) -{ - path cwd; - ErrorHandler err("canonical", ec, &orig_p, &cwd); +path __canonical(path const& orig_p, error_code* ec) { + path cwd; + ErrorHandler err("canonical", ec, &orig_p, &cwd); - path p = __do_absolute(orig_p, &cwd, ec); - char buff[PATH_MAX + 1]; - char *ret; - if ((ret = ::realpath(p.c_str(), buff)) == nullptr) - return err.report(capture_errno()); - return {ret}; + path p = __do_absolute(orig_p, &cwd, ec); + char buff[PATH_MAX + 1]; + char* ret; + if ((ret = ::realpath(p.c_str(), buff)) == nullptr) + return err.report(capture_errno()); + return {ret}; } void __copy(const path& from, const path& to, copy_options options, - error_code *ec) -{ + error_code* ec) { ErrorHandler err("copy", ec, &from, &to); const bool sym_status = bool( @@ -570,65 +568,65 @@ void __copy(const path& from, const path& to, copy_options options, return err.report(errc::function_not_supported); } - if (ec) ec->clear(); - - if (is_symlink(f)) { - if (bool(copy_options::skip_symlinks & options)) { - // do nothing - } else if (not exists(t)) { - __copy_symlink(from, to, ec); - } else { - return err.report(errc::file_exists); - } - return; + if (ec) + ec->clear(); + + if (is_symlink(f)) { + if (bool(copy_options::skip_symlinks & options)) { + // do nothing + } else if (not exists(t)) { + __copy_symlink(from, to, ec); + } else { + return err.report(errc::file_exists); + } + return; + } else if (is_regular_file(f)) { + if (bool(copy_options::directories_only & options)) { + // do nothing + } else if (bool(copy_options::create_symlinks & options)) { + __create_symlink(from, to, ec); + } else if (bool(copy_options::create_hard_links & options)) { + __create_hard_link(from, to, ec); + } else if (is_directory(t)) { + __copy_file(from, to / from.filename(), options, ec); + } else { + __copy_file(from, to, options, ec); } - else if (is_regular_file(f)) { - if (bool(copy_options::directories_only & options)) { - // do nothing - } - else if (bool(copy_options::create_symlinks & options)) { - __create_symlink(from, to, ec); - } - else if (bool(copy_options::create_hard_links & options)) { - __create_hard_link(from, to, ec); - } - else if (is_directory(t)) { - __copy_file(from, to / from.filename(), options, ec); - } else { - __copy_file(from, to, options, ec); - } + return; + } else if (is_directory(f) && bool(copy_options::create_symlinks & options)) { + return err.report(errc::is_a_directory); + } else if (is_directory(f) && (bool(copy_options::recursive & options) || + copy_options::none == options)) { + + if (!exists(t)) { + // create directory to with attributes from 'from'. + __create_directory(to, from, ec); + if (ec && *ec) { return; + } } - else if (is_directory(f) && bool(copy_options::create_symlinks & options)) { - return err.report(errc::is_a_directory); + directory_iterator it = + ec ? directory_iterator(from, *ec) : directory_iterator(from); + if (ec && *ec) { + return; } - else if (is_directory(f) && (bool(copy_options::recursive & options) || - copy_options::none == options)) { - - if (!exists(t)) { - // create directory to with attributes from 'from'. - __create_directory(to, from, ec); - if (ec && *ec) { return; } - } - directory_iterator it = ec ? directory_iterator(from, *ec) - : directory_iterator(from); - if (ec && *ec) { return; } - error_code m_ec2; - for (; it != directory_iterator(); it.increment(m_ec2)) { - if (m_ec2) { - return err.report(m_ec2); - } - __copy(it->path(), to / it->path().filename(), - options | copy_options::__in_recursive_copy, ec); - if (ec && *ec) { return; } - } + error_code m_ec2; + for (; it != directory_iterator(); it.increment(m_ec2)) { + if (m_ec2) { + return err.report(m_ec2); + } + __copy(it->path(), to / it->path().filename(), + options | copy_options::__in_recursive_copy, ec); + if (ec && *ec) { + return; + } } + } } namespace detail { namespace { - #ifdef _LIBCPP_USE_SENDFILE bool copy_file_impl_sendfile(FileDescriptor& read_fd, FileDescriptor& write_fd, error_code& ec) { @@ -721,8 +719,7 @@ bool copy_file_impl(FileDescriptor& from, FileDescriptor& to, error_code& ec) { } // namespace detail bool __copy_file(const path& from, const path& to, copy_options options, - error_code *ec) -{ + error_code* ec) { using detail::FileDescriptor; ErrorHandler err("copy_file", ec, &to, &from); @@ -811,18 +808,18 @@ bool __copy_file(const path& from, const path& to, copy_options options, } void __copy_symlink(const path& existing_symlink, const path& new_symlink, - error_code *ec) -{ - const path real_path(__read_symlink(existing_symlink, ec)); - if (ec && *ec) { return; } - // NOTE: proposal says you should detect if you should call - // create_symlink or create_directory_symlink. I don't think this - // is needed with POSIX - __create_symlink(real_path, new_symlink, ec); -} - -bool __create_directories(const path& p, error_code *ec) -{ + error_code* ec) { + const path real_path(__read_symlink(existing_symlink, ec)); + if (ec && *ec) { + return; + } + // NOTE: proposal says you should detect if you should call + // create_symlink or create_directory_symlink. I don't think this + // is needed with POSIX + __create_symlink(real_path, new_symlink, ec); +} + +bool __create_directories(const path& p, error_code* ec) { ErrorHandler err("create_directories", ec, &p); error_code m_ec; @@ -846,11 +843,10 @@ bool __create_directories(const path& p, error_code *ec) } } } - return __create_directory(p, ec); + return __create_directory(p, ec); } -bool __create_directory(const path& p, error_code *ec) -{ +bool __create_directory(const path& p, error_code* ec) { ErrorHandler err("create_directory", ec, &p); if (::mkdir(p.c_str(), static_cast(perms::all)) == 0) @@ -860,9 +856,7 @@ bool __create_directory(const path& p, error_code *ec) return false; } -bool __create_directory(path const & p, path const & attributes, - error_code *ec) -{ +bool __create_directory(path const& p, path const& attributes, error_code* ec) { ErrorHandler err("create_directory", ec, &p, &attributes); StatT attr_stat; @@ -871,7 +865,8 @@ bool __create_directory(path const & p, path const & attributes, if (!status_known(st)) return err.report(mec); if (!is_directory(st)) - return err.report(errc::not_a_directory, "the specified attribute path is invalid"); + return err.report(errc::not_a_directory, + "the specified attribute path is invalid"); if (::mkdir(p.c_str(), attr_stat.st_mode) == 0) return true; @@ -887,19 +882,19 @@ void __create_directory_symlink(path const& from, path const& to, return err.report(capture_errno()); } -void __create_hard_link(const path& from, const path& to, error_code *ec){ +void __create_hard_link(const path& from, const path& to, error_code* ec) { ErrorHandler err("create_hard_link", ec, &from, &to); if (::link(from.c_str(), to.c_str()) == -1) return err.report(capture_errno()); } -void __create_symlink(path const & from, path const & to, error_code *ec) { +void __create_symlink(path const& from, path const& to, error_code* ec) { ErrorHandler err("create_symlink", ec, &from, &to); if (::symlink(from.c_str(), to.c_str()) == -1) return err.report(capture_errno()); } -path __current_path(error_code *ec) { +path __current_path(error_code* ec) { ErrorHandler err("current_path", ec); auto size = ::pathconf(".", _PC_PATH_MAX); @@ -913,14 +908,13 @@ path __current_path(error_code *ec) { return {buff.get()}; } -void __current_path(const path& p, error_code *ec) { +void __current_path(const path& p, error_code* ec) { ErrorHandler err("current_path", ec, &p); if (::chdir(p.c_str()) == -1) err.report(capture_errno()); } -bool __equivalent(const path& p1, const path& p2, error_code *ec) -{ +bool __equivalent(const path& p1, const path& p2, error_code* ec) { ErrorHandler err("equivalent", ec, &p1, &p2); error_code ec1, ec2; @@ -935,9 +929,7 @@ bool __equivalent(const path& p1, const path& p2, error_code *ec) return detail::stat_equivalent(st1, st2); } - -uintmax_t __file_size(const path& p, error_code *ec) -{ +uintmax_t __file_size(const path& p, error_code* ec) { ErrorHandler err("file_size", ec, &p); error_code m_ec; @@ -950,12 +942,11 @@ uintmax_t __file_size(const path& p, error_code *ec) m_ec = make_error_code(error_kind); return err.report(m_ec); } - // is_regular_file(p) == true - return static_cast(st.st_size); + // is_regular_file(p) == true + return static_cast(st.st_size); } -uintmax_t __hard_link_count(const path& p, error_code *ec) -{ +uintmax_t __hard_link_count(const path& p, error_code* ec) { ErrorHandler err("hard_link_count", ec, &p); error_code m_ec; @@ -966,9 +957,7 @@ uintmax_t __hard_link_count(const path& p, error_code *ec) return static_cast(st.st_nlink); } - -bool __fs_is_empty(const path& p, error_code *ec) -{ +bool __fs_is_empty(const path& p, error_code* ec) { ErrorHandler err("is_empty", ec, &p); error_code m_ec; @@ -1001,52 +990,47 @@ static file_time_type __extract_last_write_time(const path& p, const StatT& st, return fs_time::convert_from_timespec(ts); } -file_time_type __last_write_time(const path& p, error_code *ec) -{ - using namespace chrono; - ErrorHandler err("last_write_time", ec, &p); +file_time_type __last_write_time(const path& p, error_code* ec) { + using namespace chrono; + ErrorHandler err("last_write_time", ec, &p); - error_code m_ec; - StatT st; - detail::posix_stat(p, st, &m_ec); - if (m_ec) - return err.report(m_ec); - return __extract_last_write_time(p, st, ec); + error_code m_ec; + StatT st; + detail::posix_stat(p, st, &m_ec); + if (m_ec) + return err.report(m_ec); + return __extract_last_write_time(p, st, ec); } -void __last_write_time(const path& p, file_time_type new_time, - error_code *ec) -{ - using detail::fs_time; - ErrorHandler err("last_write_time", ec, &p); +void __last_write_time(const path& p, file_time_type new_time, error_code* ec) { + using detail::fs_time; + ErrorHandler err("last_write_time", ec, &p); - error_code m_ec; - array tbuf; + error_code m_ec; + array tbuf; #if !defined(_LIBCPP_USE_UTIMENSAT) - // This implementation has a race condition between determining the - // last access time and attempting to set it to the same value using - // ::utimes - StatT st; - file_status fst = detail::posix_stat(p, st, &m_ec); - if (m_ec) - return err.report(m_ec); - tbuf[0] = detail::extract_atime(st); + // This implementation has a race condition between determining the + // last access time and attempting to set it to the same value using + // ::utimes + StatT st; + file_status fst = detail::posix_stat(p, st, &m_ec); + if (m_ec) + return err.report(m_ec); + tbuf[0] = detail::extract_atime(st); #else - tbuf[0].tv_sec = 0; - tbuf[0].tv_nsec = UTIME_OMIT; + tbuf[0].tv_sec = 0; + tbuf[0].tv_nsec = UTIME_OMIT; #endif - if (!fs_time::convert_to_timespec(tbuf[1], new_time)) - return err.report(errc::value_too_large); + if (!fs_time::convert_to_timespec(tbuf[1], new_time)) + return err.report(errc::value_too_large); - detail::set_file_times(p, tbuf, m_ec); - if (m_ec) - return err.report(m_ec); + detail::set_file_times(p, tbuf, m_ec); + if (m_ec) + return err.report(m_ec); } - void __permissions(const path& p, perms prms, perm_options opts, - error_code *ec) -{ + error_code* ec) { ErrorHandler err("permissions", ec, &p); auto has_opt = [&](perm_options o) { return bool(o & opts); }; @@ -1074,24 +1058,23 @@ void __permissions(const path& p, perms prms, perm_options opts, else if (remove_perms) prms = st.permissions() & ~prms; } - const auto real_perms = detail::posix_convert_perms(prms); + const auto real_perms = detail::posix_convert_perms(prms); -# if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) - const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0; - if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { - return err.report(capture_errno()); - } -# else - if (set_sym_perms) - return err.report(errc::operation_not_supported); - if (::chmod(p.c_str(), real_perms) == -1) { - return err.report(capture_errno()); - } -# endif +#if defined(AT_SYMLINK_NOFOLLOW) && defined(AT_FDCWD) + const int flags = set_sym_perms ? AT_SYMLINK_NOFOLLOW : 0; + if (::fchmodat(AT_FDCWD, p.c_str(), real_perms, flags) == -1) { + return err.report(capture_errno()); + } +#else + if (set_sym_perms) + return err.report(errc::operation_not_supported); + if (::chmod(p.c_str(), real_perms) == -1) { + return err.report(capture_errno()); + } +#endif } - -path __read_symlink(const path& p, error_code *ec) { +path __read_symlink(const path& p, error_code* ec) { ErrorHandler err("read_symlink", ec, &p); char buff[PATH_MAX + 1]; @@ -1100,47 +1083,49 @@ path __read_symlink(const path& p, error_code *ec) { if ((ret = ::readlink(p.c_str(), buff, PATH_MAX)) == -1) { return err.report(capture_errno()); } - _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO"); - _LIBCPP_ASSERT(ret > 0, "TODO"); - buff[ret] = 0; - return {buff}; + _LIBCPP_ASSERT(ret <= PATH_MAX, "TODO"); + _LIBCPP_ASSERT(ret > 0, "TODO"); + buff[ret] = 0; + return {buff}; } - -bool __remove(const path& p, error_code *ec) { +bool __remove(const path& p, error_code* ec) { ErrorHandler err("remove", ec, &p); if (::remove(p.c_str()) == -1) { if (errno != ENOENT) err.report(capture_errno()); return false; } - return true; + return true; } namespace { -uintmax_t remove_all_impl(path const & p, error_code& ec) -{ - const auto npos = static_cast(-1); - const file_status st = __symlink_status(p, &ec); - if (ec) return npos; - uintmax_t count = 1; - if (is_directory(st)) { - for (directory_iterator it(p, ec); !ec && it != directory_iterator(); - it.increment(ec)) { - auto other_count = remove_all_impl(it->path(), ec); - if (ec) return npos; - count += other_count; - } - if (ec) return npos; +uintmax_t remove_all_impl(path const& p, error_code& ec) { + const auto npos = static_cast(-1); + const file_status st = __symlink_status(p, &ec); + if (ec) + return npos; + uintmax_t count = 1; + if (is_directory(st)) { + for (directory_iterator it(p, ec); !ec && it != directory_iterator(); + it.increment(ec)) { + auto other_count = remove_all_impl(it->path(), ec); + if (ec) + return npos; + count += other_count; } - if (!__remove(p, &ec)) return npos; - return count; + if (ec) + return npos; + } + if (!__remove(p, &ec)) + return npos; + return count; } } // end namespace -uintmax_t __remove_all(const path& p, error_code *ec) { +uintmax_t __remove_all(const path& p, error_code* ec) { ErrorHandler err("remove_all", ec, &p); error_code mec; @@ -1150,22 +1135,22 @@ uintmax_t __remove_all(const path& p, error_code *ec) { return 0; return err.report(mec); } - return count; + return count; } -void __rename(const path& from, const path& to, error_code *ec) { +void __rename(const path& from, const path& to, error_code* ec) { ErrorHandler err("rename", ec, &from, &to); if (::rename(from.c_str(), to.c_str()) == -1) err.report(capture_errno()); } -void __resize_file(const path& p, uintmax_t size, error_code *ec) { +void __resize_file(const path& p, uintmax_t size, error_code* ec) { ErrorHandler err("resize_file", ec, &p); if (::truncate(p.c_str(), static_cast< ::off_t>(size)) == -1) return err.report(capture_errno()); } -space_info __space(const path& p, error_code *ec) { +space_info __space(const path& p, error_code* ec) { ErrorHandler err("space", ec, &p); space_info si; struct statvfs m_svfs = {}; @@ -1174,24 +1159,24 @@ space_info __space(const path& p, error_code *ec) { si.capacity = si.free = si.available = static_cast(-1); return si; } - // Multiply with overflow checking. - auto do_mult = [&](uintmax_t& out, uintmax_t other) { - out = other * m_svfs.f_frsize; - if (other == 0 || out / other != m_svfs.f_frsize) - out = static_cast(-1); - }; - do_mult(si.capacity, m_svfs.f_blocks); - do_mult(si.free, m_svfs.f_bfree); - do_mult(si.available, m_svfs.f_bavail); - return si; + // Multiply with overflow checking. + auto do_mult = [&](uintmax_t& out, uintmax_t other) { + out = other * m_svfs.f_frsize; + if (other == 0 || out / other != m_svfs.f_frsize) + out = static_cast(-1); + }; + do_mult(si.capacity, m_svfs.f_blocks); + do_mult(si.free, m_svfs.f_bfree); + do_mult(si.available, m_svfs.f_bavail); + return si; } -file_status __status(const path& p, error_code *ec) { - return detail::posix_stat(p, ec); +file_status __status(const path& p, error_code* ec) { + return detail::posix_stat(p, ec); } -file_status __symlink_status(const path& p, error_code *ec) { - return detail::posix_lstat(p, ec); +file_status __symlink_status(const path& p, error_code* ec) { + return detail::posix_lstat(p, ec); } path __temp_directory_path(error_code* ec) { @@ -1219,8 +1204,7 @@ path __temp_directory_path(error_code* ec) { return p; } - -path __weakly_canonical(const path& p, error_code *ec) { +path __weakly_canonical(const path& p, error_code* ec) { ErrorHandler err("weakly_canonical", ec, &p); if (p.empty()) @@ -1248,10 +1232,11 @@ path __weakly_canonical(const path& p, error_code *ec) { } if (PP.State == PathParser::PS_BeforeBegin) result = __canonical("", ec); - if (ec) ec->clear(); + if (ec) + ec->clear(); if (DNEParts.empty()) return result; - for (auto It=DNEParts.rbegin(); It != DNEParts.rend(); ++It) + for (auto It = DNEParts.rbegin(); It != DNEParts.rend(); ++It) result /= *It; return result.lexically_normal(); } @@ -1262,56 +1247,52 @@ path __weakly_canonical(const path& p, error_code *ec) { constexpr path::value_type path::preferred_separator; -path & path::replace_extension(path const & replacement) -{ - path p = extension(); - if (not p.empty()) { - __pn_.erase(__pn_.size() - p.native().size()); - } - if (!replacement.empty()) { - if (replacement.native()[0] != '.') { - __pn_ += "."; - } - __pn_.append(replacement.__pn_); +path& path::replace_extension(path const& replacement) { + path p = extension(); + if (not p.empty()) { + __pn_.erase(__pn_.size() - p.native().size()); + } + if (!replacement.empty()) { + if (replacement.native()[0] != '.') { + __pn_ += "."; } - return *this; + __pn_.append(replacement.__pn_); + } + return *this; } /////////////////////////////////////////////////////////////////////////////// // path.decompose -string_view_t path::__root_name() const -{ - auto PP = PathParser::CreateBegin(__pn_); - if (PP.State == PathParser::PS_InRootName) - return *PP; - return {}; +string_view_t path::__root_name() const { + auto PP = PathParser::CreateBegin(__pn_); + if (PP.State == PathParser::PS_InRootName) + return *PP; + return {}; } -string_view_t path::__root_directory() const -{ - auto PP = PathParser::CreateBegin(__pn_); - if (PP.State == PathParser::PS_InRootName) - ++PP; - if (PP.State == PathParser::PS_InRootDir) - return *PP; - return {}; +string_view_t path::__root_directory() const { + auto PP = PathParser::CreateBegin(__pn_); + if (PP.State == PathParser::PS_InRootName) + ++PP; + if (PP.State == PathParser::PS_InRootDir) + return *PP; + return {}; } -string_view_t path::__root_path_raw() const -{ - auto PP = PathParser::CreateBegin(__pn_); - if (PP.State == PathParser::PS_InRootName) { - auto NextCh = PP.peek(); - if (NextCh && *NextCh == '/') { - ++PP; - return createView(__pn_.data(), &PP.RawEntry.back()); - } - return PP.RawEntry; +string_view_t path::__root_path_raw() const { + auto PP = PathParser::CreateBegin(__pn_); + if (PP.State == PathParser::PS_InRootName) { + auto NextCh = PP.peek(); + if (NextCh && *NextCh == '/') { + ++PP; + return createView(__pn_.data(), &PP.RawEntry.back()); } - if (PP.State == PathParser::PS_InRootDir) - return *PP; - return {}; + return PP.RawEntry; + } + if (PP.State == PathParser::PS_InRootDir) + return *PP; + return {}; } static bool ConsumeRootDir(PathParser* PP) { @@ -1320,62 +1301,57 @@ static bool ConsumeRootDir(PathParser* PP) { return PP->State == PathParser::PS_AtEnd; } -string_view_t path::__relative_path() const -{ +string_view_t path::__relative_path() const { + auto PP = PathParser::CreateBegin(__pn_); + if (ConsumeRootDir(&PP)) + return {}; + return createView(PP.RawEntry.data(), &__pn_.back()); +} + +string_view_t path::__parent_path() const { + if (empty()) + return {}; + // Determine if we have a root path but not a relative path. In that case + // return *this. + { auto PP = PathParser::CreateBegin(__pn_); if (ConsumeRootDir(&PP)) + return __pn_; + } + // Otherwise remove a single element from the end of the path, and return + // a string representing that path + { + auto PP = PathParser::CreateEnd(__pn_); + --PP; + if (PP.RawEntry.data() == __pn_.data()) return {}; - return createView(PP.RawEntry.data(), &__pn_.back()); + --PP; + return createView(__pn_.data(), &PP.RawEntry.back()); + } } -string_view_t path::__parent_path() const -{ - if (empty()) +string_view_t path::__filename() const { + if (empty()) + return {}; + { + PathParser PP = PathParser::CreateBegin(__pn_); + if (ConsumeRootDir(&PP)) return {}; - // Determine if we have a root path but not a relative path. In that case - // return *this. - { - auto PP = PathParser::CreateBegin(__pn_); - if (ConsumeRootDir(&PP)) - return __pn_; - } - // Otherwise remove a single element from the end of the path, and return - // a string representing that path - { - auto PP = PathParser::CreateEnd(__pn_); - --PP; - if (PP.RawEntry.data() == __pn_.data()) - return {}; - --PP; - return createView(__pn_.data(), &PP.RawEntry.back()); - } -} - -string_view_t path::__filename() const -{ - if (empty()) return {}; - { - PathParser PP = PathParser::CreateBegin(__pn_); - if (ConsumeRootDir(&PP)) - return {}; - } - return *(--PathParser::CreateEnd(__pn_)); + } + return *(--PathParser::CreateEnd(__pn_)); } -string_view_t path::__stem() const -{ - return parser::separate_filename(__filename()).first; +string_view_t path::__stem() const { + return parser::separate_filename(__filename()).first; } -string_view_t path::__extension() const -{ - return parser::separate_filename(__filename()).second; +string_view_t path::__extension() const { + return parser::separate_filename(__filename()).second; } //////////////////////////////////////////////////////////////////////////// // path.gen - enum PathPartKind : unsigned char { PK_None, PK_RootSep, @@ -1456,7 +1432,7 @@ path path::lexically_normal() const { } // [fs.path.generic]p6.8: If the path is empty, add a dot. if (Parts.empty()) - return "."; + return "."; // [fs.path.generic]p6.7: If the last filename is dot-dot, remove any // trailing directory-separator. @@ -1464,7 +1440,7 @@ path path::lexically_normal() const { path Result; Result.__pn_.reserve(Parts.size() + NewPathSize + NeedTrailingSep); - for (auto &PK : Parts) + for (auto& PK : Parts) Result /= PK.first; if (NeedTrailingSep) @@ -1490,8 +1466,8 @@ path path::lexically_relative(const path& base) const { auto PP = PathParser::CreateBegin(__pn_); auto PPBase = PathParser::CreateBegin(base.__pn_); auto CheckIterMismatchAtBase = [&]() { - return PP.State != PPBase.State && ( - PP.inRootPath() || PPBase.inRootPath()); + return PP.State != PPBase.State && + (PP.inRootPath() || PPBase.inRootPath()); }; if (PP.State == PathParser::PS_InRootName && PPBase.State == PathParser::PS_InRootName) { @@ -1500,8 +1476,10 @@ path path::lexically_relative(const path& base) const { } else if (CheckIterMismatchAtBase()) return {}; - if (PP.inRootPath()) ++PP; - if (PPBase.inRootPath()) ++PPBase; + if (PP.inRootPath()) + ++PP; + if (PPBase.inRootPath()) + ++PPBase; if (CheckIterMismatchAtBase()) return {}; } @@ -1509,8 +1487,7 @@ path path::lexically_relative(const path& base) const { // Find the first mismatching element auto PP = PathParser::CreateBegin(__pn_); auto PPBase = PathParser::CreateBegin(base.__pn_); - while (PP && PPBase && PP.State == PPBase.State && - *PP == *PPBase) { + while (PP && PPBase && PP.State == PPBase.State && *PP == *PPBase) { ++PP; ++PPBase; } @@ -1539,18 +1516,20 @@ 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) return res; - ++PP; ++PP2; - } - if (PP.State == PP2.State && !PP) - return 0; - if (!PP) - return -1; - return 1; + auto PP = PathParser::CreateBegin(__pn_); + auto PP2 = PathParser::CreateBegin(__s); + while (PP && PP2) { + int res = (*PP).compare(*PP2); + if (res != 0) + return res; + ++PP; + ++PP2; + } + if (PP.State == PP2.State && !PP) + return 0; + if (!PP) + return -1; + return 1; } //////////////////////////////////////////////////////////////////////////// @@ -1568,23 +1547,21 @@ size_t hash_value(const path& __p) noexcept { //////////////////////////////////////////////////////////////////////////// // path.itr -path::iterator path::begin() const -{ - auto PP = PathParser::CreateBegin(__pn_); - iterator it; - it.__path_ptr_ = this; - it.__state_ = static_cast(PP.State); - it.__entry_ = PP.RawEntry; - it.__stashed_elem_.__assign_view(*PP); - return it; +path::iterator path::begin() const { + auto PP = PathParser::CreateBegin(__pn_); + iterator it; + it.__path_ptr_ = this; + it.__state_ = static_cast(PP.State); + it.__entry_ = PP.RawEntry; + it.__stashed_elem_.__assign_view(*PP); + return it; } -path::iterator path::end() const -{ - iterator it{}; - it.__state_ = path::iterator::_AtEnd; - it.__path_ptr_ = this; - return it; +path::iterator path::end() const { + iterator it{}; + it.__state_ = path::iterator::_AtEnd; + it.__path_ptr_ = this; + return it; } path::iterator& path::iterator::__increment() { @@ -1706,4 +1683,4 @@ error_code directory_entry::__do_refresh() noexcept { } #endif -_LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM +_LIBCPP_END_NAMESPACE_FILESYSTEM diff --git a/test/libcxx/double_include.sh.cpp b/test/libcxx/double_include.sh.cpp index dfc3d0116..c98cc8065 100644 --- a/test/libcxx/double_include.sh.cpp +++ b/test/libcxx/double_include.sh.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include diff --git a/test/libcxx/experimental/filesystem/version.pass.cpp b/test/libcxx/experimental/filesystem/version.pass.cpp index 723380a26..d5f36a6b3 100644 --- a/test/libcxx/experimental/filesystem/version.pass.cpp +++ b/test/libcxx/experimental/filesystem/version.pass.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 - // #include diff --git a/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp b/test/libcxx/input.output/filesystems/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp similarity index 96% rename from test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp rename to test/libcxx/input.output/filesystems/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp index 7f4ed6730..6372755fc 100644 --- a/test/libcxx/experimental/filesystem/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp +++ b/test/libcxx/input.output/filesystems/class.directory_entry/directory_entry.mods/last_write_time.sh.cpp @@ -9,11 +9,11 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry -// RUN: %build -I%libcxx_src_root/src/experimental/filesystem +// RUN: %build -I%libcxx_src_root/src/filesystem // RUN: %run #include "filesystem_include.hpp" diff --git a/test/libcxx/experimental/filesystem/class.path/path.itr/iterator_db.pass.cpp b/test/libcxx/input.output/filesystems/class.path/path.itr/iterator_db.pass.cpp similarity index 93% rename from test/libcxx/experimental/filesystem/class.path/path.itr/iterator_db.pass.cpp rename to test/libcxx/input.output/filesystems/class.path/path.itr/iterator_db.pass.cpp index b8b7124ad..405f9abc2 100644 --- a/test/libcxx/experimental/filesystem/class.path/path.itr/iterator_db.pass.cpp +++ b/test/libcxx/input.output/filesystems/class.path/path.itr/iterator_db.pass.cpp @@ -13,13 +13,13 @@ // MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS // MODULES_DEFINES: _LIBCPP_DEBUG=0 -// +// // class path #define _LIBCPP_DEBUG 0 #define _LIBCPP_DEBUG_USE_EXCEPTIONS -#include +#include "filesystem_include.hpp" #include #include #include @@ -27,8 +27,6 @@ #include "test_macros.h" #include "filesystem_test_helper.hpp" -namespace fs = std::experimental::filesystem; - int main() { using namespace fs; using ExType = std::__libcpp_debug_exception; diff --git a/test/libcxx/experimental/filesystem/class.path/path.itr/reverse_iterator_produces_diagnostic.fail.cpp b/test/libcxx/input.output/filesystems/class.path/path.itr/reverse_iterator_produces_diagnostic.fail.cpp similarity index 87% rename from test/libcxx/experimental/filesystem/class.path/path.itr/reverse_iterator_produces_diagnostic.fail.cpp rename to test/libcxx/input.output/filesystems/class.path/path.itr/reverse_iterator_produces_diagnostic.fail.cpp index 5a6f5304a..992cdebb5 100644 --- a/test/libcxx/experimental/filesystem/class.path/path.itr/reverse_iterator_produces_diagnostic.fail.cpp +++ b/test/libcxx/input.output/filesystems/class.path/path.itr/reverse_iterator_produces_diagnostic.fail.cpp @@ -9,16 +9,14 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path -#include +#include "filesystem_include.hpp" #include -namespace fs = std::experimental::filesystem; - int main() { using namespace fs; using RIt = std::reverse_iterator; diff --git a/test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp b/test/libcxx/input.output/filesystems/class.path/path.req/is_pathable.pass.cpp similarity index 96% rename from test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp rename to test/libcxx/input.output/filesystems/class.path/path.req/is_pathable.pass.cpp index 61d322524..ff0cc5935 100644 --- a/test/libcxx/experimental/filesystem/class.path/path.req/is_pathable.pass.cpp +++ b/test/libcxx/input.output/filesystems/class.path/path.req/is_pathable.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // template struct __is_pathable @@ -21,7 +21,7 @@ // * A character array, which points to a NTCTS after array-to-pointer decay. -#include +#include "filesystem_include.hpp" #include #include @@ -30,8 +30,6 @@ #include "min_allocator.h" #include "constexpr_char_traits.hpp" -namespace fs = std::experimental::filesystem; - using fs::__is_pathable; template diff --git a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp b/test/libcxx/input.output/filesystems/convert_file_time.sh.cpp similarity index 98% rename from test/libcxx/experimental/filesystem/convert_file_time.sh.cpp rename to test/libcxx/input.output/filesystems/convert_file_time.sh.cpp index 918236641..21a1a4992 100644 --- a/test/libcxx/experimental/filesystem/convert_file_time.sh.cpp +++ b/test/libcxx/input.output/filesystems/convert_file_time.sh.cpp @@ -9,14 +9,14 @@ // UNSUPPORTED: c++98, c++03, c++11 -// +// // typedef TrivialClock file_time_type; -// RUN: %build -I%libcxx_src_root/src/experimental/filesystem +// RUN: %build -I%libcxx_src_root/src/filesystem // RUN: %run -#include +#include #include #include #include @@ -30,7 +30,7 @@ #endif using namespace std::chrono; -namespace fs = std::experimental::filesystem; +namespace fs = std::__fs::filesystem; using fs::file_time_type; using fs::detail::time_util; diff --git a/test/libcxx/experimental/filesystem/lit.local.cfg b/test/libcxx/input.output/filesystems/lit.local.cfg similarity index 100% rename from test/libcxx/experimental/filesystem/lit.local.cfg rename to test/libcxx/input.output/filesystems/lit.local.cfg diff --git a/test/libcxx/input.output/filesystems/version.pass.cpp b/test/libcxx/input.output/filesystems/version.pass.cpp new file mode 100644 index 000000000..f680217ef --- /dev/null +++ b/test/libcxx/input.output/filesystems/version.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/test/std/input.output/file.streams/fstreams/filebuf.members/open_path.pass.cpp b/test/std/input.output/file.streams/fstreams/filebuf.members/open_path.pass.cpp new file mode 100644 index 000000000..02e2b607e --- /dev/null +++ b/test/std/input.output/file.streams/fstreams/filebuf.members/open_path.pass.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// basic_filebuf* open(const filesystem::path& p, ios_base::openmode mode); + +#include +#include +#include +#include "platform_support.h" + +namespace fs = std::filesystem; + +int main() { + + fs::path p = get_temp_file_name(); + { + std::filebuf f; + assert(f.open(p, std::ios_base::out) != 0); + assert(f.is_open()); + assert(f.sputn("123", 3) == 3); + } + { + std::filebuf f; + assert(f.open(p, std::ios_base::in) != 0); + assert(f.is_open()); + assert(f.sbumpc() == '1'); + assert(f.sbumpc() == '2'); + assert(f.sbumpc() == '3'); + } + std::remove(p.c_str()); + { + std::wfilebuf f; + assert(f.open(p, std::ios_base::out) != 0); + assert(f.is_open()); + assert(f.sputn(L"123", 3) == 3); + } + { + std::wfilebuf f; + assert(f.open(p, std::ios_base::in) != 0); + assert(f.is_open()); + assert(f.sbumpc() == L'1'); + assert(f.sbumpc() == L'2'); + assert(f.sbumpc() == L'3'); + } + remove(p.c_str()); +} diff --git a/test/std/input.output/file.streams/fstreams/fstream.cons/path.pass.cpp b/test/std/input.output/file.streams/fstreams/fstream.cons/path.pass.cpp new file mode 100644 index 000000000..d9b4a8ccb --- /dev/null +++ b/test/std/input.output/file.streams/fstreams/fstream.cons/path.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// plate > +// class basic_fstream + +// explicit basic_fstream(const filesystem::path& s, +// ios_base::openmode mode = ios_base::in|ios_base::out); + +#include +#include +#include +#include "platform_support.h" + +namespace fs = std::filesystem; + +int main() { + fs::path p = get_temp_file_name(); + { + std::fstream fs(p, std::ios_base::in | std::ios_base::out | + std::ios_base::trunc); + double x = 0; + fs << 3.25; + fs.seekg(0); + fs >> x; + assert(x == 3.25); + } + std::remove(p.c_str()); + { + std::wfstream fs(p, std::ios_base::in | std::ios_base::out | + std::ios_base::trunc); + double x = 0; + fs << 3.25; + fs.seekg(0); + fs >> x; + assert(x == 3.25); + } + std::remove(p.c_str()); +} diff --git a/test/std/input.output/file.streams/fstreams/fstream.members/open_path.pass.cpp b/test/std/input.output/file.streams/fstreams/fstream.members/open_path.pass.cpp new file mode 100644 index 000000000..69cbf3f5c --- /dev/null +++ b/test/std/input.output/file.streams/fstreams/fstream.members/open_path.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// plate > +// class basic_fstream + +// void open(const filesystem::path& s, ios_base::openmode mode = ios_base::in|ios_base::out); + +#include +#include +#include +#include "platform_support.h" + +int main() { + std::filesystem::path p = get_temp_file_name(); + { + std::fstream stream; + assert(!stream.is_open()); + stream.open(p, + std::ios_base::in | std::ios_base::out | std::ios_base::trunc); + assert(stream.is_open()); + double x = 0; + stream << 3.25; + stream.seekg(0); + stream >> x; + assert(x == 3.25); + } + std::remove(p.c_str()); + { + std::wfstream stream; + assert(!stream.is_open()); + stream.open(p, + std::ios_base::in | std::ios_base::out | std::ios_base::trunc); + assert(stream.is_open()); + double x = 0; + stream << 3.25; + stream.seekg(0); + stream >> x; + assert(x == 3.25); + } + std::remove(p.c_str()); +} diff --git a/test/std/input.output/file.streams/fstreams/ifstream.cons/path.pass.cpp b/test/std/input.output/file.streams/fstreams/ifstream.cons/path.pass.cpp new file mode 100644 index 000000000..99eae3a28 --- /dev/null +++ b/test/std/input.output/file.streams/fstreams/ifstream.cons/path.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template > +// class basic_ifstream + +// explicit basic_ifstream(const filesystem::path& s, +// ios_base::openmode mode = ios_base::in); + +#include +#include +#include + +namespace fs = std::filesystem; + +int main() { + { + fs::path p; + static_assert(!std::is_convertible::value, + "ctor should be explicit"); + static_assert(std::is_constructible::value, + ""); + } + { + std::ifstream fs(fs::path("test.dat")); + double x = 0; + fs >> x; + assert(x == 3.25); + } + // std::ifstream(const fs::path&, std::ios_base::openmode) is tested in + // test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp + // which creates writable files. + { + std::wifstream fs(fs::path("test.dat")); + double x = 0; + fs >> x; + assert(x == 3.25); + } + // std::wifstream(const fs::path&, std::ios_base::openmode) is tested in + // test/std/input.output/file.streams/fstreams/ofstream.cons/string.pass.cpp + // which creates writable files. +} diff --git a/test/std/input.output/file.streams/fstreams/ifstream.members/open_path.pass.cpp b/test/std/input.output/file.streams/fstreams/ifstream.members/open_path.pass.cpp new file mode 100644 index 000000000..82f7c64eb --- /dev/null +++ b/test/std/input.output/file.streams/fstreams/ifstream.members/open_path.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// template > +// class basic_ifstream + +// void open(const filesystem::path& s, ios_base::openmode mode = ios_base::in); + +#include +#include +#include + +int main() { + { + std::ifstream fs; + assert(!fs.is_open()); + char c = 'a'; + fs >> c; + assert(fs.fail()); + assert(c == 'a'); + fs.open(std::filesystem::path("test.dat")); + assert(fs.is_open()); + fs >> c; + assert(c == 'r'); + } + { + std::wifstream fs; + assert(!fs.is_open()); + wchar_t c = L'a'; + fs >> c; + assert(fs.fail()); + assert(c == L'a'); + fs.open(std::filesystem::path("test.dat")); + assert(fs.is_open()); + fs >> c; + assert(c == L'r'); + } +} diff --git a/test/std/input.output/file.streams/fstreams/ofstream.cons/path.pass.cpp b/test/std/input.output/file.streams/fstreams/ofstream.cons/path.pass.cpp new file mode 100644 index 000000000..9a23384b0 --- /dev/null +++ b/test/std/input.output/file.streams/fstreams/ofstream.cons/path.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// plate > +// class basic_ofstream + +// explicit basic_ofstream(const filesystem::path& s, ios_base::openmode mode = ios_base::out); + +#include +#include +#include +#include "platform_support.h" + +namespace fs = std::filesystem; + +int main() { + fs::path p = get_temp_file_name(); + { + static_assert(!std::is_convertible::value, + "ctor should be explicit"); + static_assert(std::is_constructible::value, + ""); + } + { + std::ofstream stream(p); + stream << 3.25; + } + { + std::ifstream stream(p); + double x = 0; + stream >> x; + assert(x == 3.25); + } + { + std::ifstream stream(p, std::ios_base::out); + double x = 0; + stream >> x; + assert(x == 3.25); + } + std::remove(p.c_str()); + { + std::wofstream stream(p); + stream << 3.25; + } + { + std::wifstream stream(p); + double x = 0; + stream >> x; + assert(x == 3.25); + } + { + std::wifstream stream(p, std::ios_base::out); + double x = 0; + stream >> x; + assert(x == 3.25); + } + std::remove(p.c_str()); +} diff --git a/test/std/input.output/file.streams/fstreams/ofstream.members/open_path.pass.cpp b/test/std/input.output/file.streams/fstreams/ofstream.members/open_path.pass.cpp new file mode 100644 index 000000000..867998bb7 --- /dev/null +++ b/test/std/input.output/file.streams/fstreams/ofstream.members/open_path.pass.cpp @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// plate > +// class basic_ofstream + +// void open(const filesystem::path& s, ios_base::openmode mode = ios_base::out); + +#include +#include +#include +#include "platform_support.h" + +namespace fs = std::filesystem; + +int main() { + fs::path p = get_temp_file_name(); + { + std::ofstream fs; + assert(!fs.is_open()); + char c = 'a'; + fs << c; + assert(fs.fail()); + fs.open(p); + assert(fs.is_open()); + fs << c; + } + { + std::ifstream fs(p.c_str()); + char c = 0; + fs >> c; + assert(c == 'a'); + } + std::remove(p.c_str()); + { + std::wofstream fs; + assert(!fs.is_open()); + wchar_t c = L'a'; + fs << c; + assert(fs.fail()); + fs.open(p); + assert(fs.is_open()); + fs << c; + } + { + std::wifstream fs(p.c_str()); + wchar_t c = 0; + fs >> c; + assert(c == L'a'); + } + std::remove(p.c_str()); +} diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/bad_symlink b/test/std/input.output/filesystems/Inputs/static_test_env/bad_symlink similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/bad_symlink rename to test/std/input.output/filesystems/Inputs/static_test_env/bad_symlink diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/afile3 b/test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/afile3 similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/afile3 rename to test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/afile3 diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/dir3/file5 b/test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/dir3/file5 similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/dir3/file5 rename to test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/dir3/file5 diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/file4 b/test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/file4 similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/file4 rename to test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/file4 diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 b/test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 rename to test/std/input.output/filesystems/Inputs/static_test_env/dir1/dir2/symlink_to_dir3 diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/dir1/file1 b/test/std/input.output/filesystems/Inputs/static_test_env/dir1/file1 similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/dir1/file1 rename to test/std/input.output/filesystems/Inputs/static_test_env/dir1/file1 diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/dir1/file2 b/test/std/input.output/filesystems/Inputs/static_test_env/dir1/file2 similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/dir1/file2 rename to test/std/input.output/filesystems/Inputs/static_test_env/dir1/file2 diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/empty_file b/test/std/input.output/filesystems/Inputs/static_test_env/empty_file similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/empty_file rename to test/std/input.output/filesystems/Inputs/static_test_env/empty_file diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/non_empty_file b/test/std/input.output/filesystems/Inputs/static_test_env/non_empty_file similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/non_empty_file rename to test/std/input.output/filesystems/Inputs/static_test_env/non_empty_file diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/symlink_to_dir b/test/std/input.output/filesystems/Inputs/static_test_env/symlink_to_dir similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/symlink_to_dir rename to test/std/input.output/filesystems/Inputs/static_test_env/symlink_to_dir diff --git a/test/std/experimental/filesystem/Inputs/static_test_env/symlink_to_empty_file b/test/std/input.output/filesystems/Inputs/static_test_env/symlink_to_empty_file similarity index 100% rename from test/std/experimental/filesystem/Inputs/static_test_env/symlink_to_empty_file rename to test/std/input.output/filesystems/Inputs/static_test_env/symlink_to_empty_file diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy.pass.cpp index f46302938..a81d5ea79 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp index 447d40985..204207276 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/copy_assign.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/default.pass.cpp similarity index 96% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/default.pass.cpp index dd4543dbb..1d83cc69d 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/default.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default_const.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/default_const.pass.cpp similarity index 96% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default_const.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/default_const.pass.cpp index a94134c15..240541d20 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/default_const.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/default_const.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: c++98, c++03 // XFAIL: apple-clang-7, clang-3.7, clang-3.8 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move.pass.cpp index f22bf1c33..238a8549e 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move_assign.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move_assign.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move_assign.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move_assign.pass.cpp index abd9bc865..f104980c9 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/move_assign.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/move_assign.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/path.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/path.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp index b6ecd3f58..b06bd1293 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.cons/path.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/assign.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/assign.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp index 70f0de3fb..d19c8c2ad 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/assign.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp index 74c73f030..575f0d59b 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/refresh.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp index 24b5ebf07..4a9b76d63 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/comparisons.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/comparisons.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp index 48997ca20..7df36fed3 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/comparisons.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/comparisons.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp index a38b10c00..04dec92c9 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_size.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp index a028de4b1..2a0d80ca6 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp index d11457d20..17124c132 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp index 3d519728c..afdd47a51 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/path.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/path.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/path.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/path.pass.cpp index 80168ef2a..2abb13df1 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/path.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/path.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp index 1f15850ce..ec654468b 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/status.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp rename to test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp index ed6aca2c7..e8850c3a7 100644 --- a/test/std/experimental/filesystem/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_entry diff --git a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy.pass.cpp b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy.pass.cpp rename to test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy.pass.cpp index 777e6144c..ac224ac7a 100644 --- a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_iterator diff --git a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp rename to test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp index 067e6c62d..3f08e4024 100644 --- a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/copy_assign.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_iterator diff --git a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/ctor.pass.cpp b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/ctor.pass.cpp rename to test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp index 6a24a52d5..0a33544c5 100644 --- a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/ctor.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_iterator diff --git a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/default_ctor.pass.cpp b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/default_ctor.pass.cpp similarity index 96% rename from test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/default_ctor.pass.cpp rename to test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/default_ctor.pass.cpp index 787f3975e..21c4ed3b7 100644 --- a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/default_ctor.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/default_ctor.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_iterator diff --git a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/increment.pass.cpp b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/increment.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/increment.pass.cpp rename to test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/increment.pass.cpp index ad55e05a7..7ec814b21 100644 --- a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/increment.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/increment.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_iterator diff --git a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move.pass.cpp b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move.pass.cpp rename to test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move.pass.cpp index 97a34a9bd..a2bf2ac9f 100644 --- a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_iterator diff --git a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp rename to test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp index 538256626..1c7224344 100644 --- a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/move_assign.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_iterator diff --git a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp rename to test/std/input.output/filesystems/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp index 95bb78c42..71e8e55ae 100644 --- a/test/std/experimental/filesystem/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.nonmembers/begin_end.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_iterator diff --git a/test/std/experimental/filesystem/class.directory_iterator/types.pass.cpp b/test/std/input.output/filesystems/class.directory_iterator/types.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.directory_iterator/types.pass.cpp rename to test/std/input.output/filesystems/class.directory_iterator/types.pass.cpp index ca583bedd..4619083e8 100644 --- a/test/std/experimental/filesystem/class.directory_iterator/types.pass.cpp +++ b/test/std/input.output/filesystems/class.directory_iterator/types.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_iterator diff --git a/test/std/experimental/filesystem/class.file_status/file_status.cons.pass.cpp b/test/std/input.output/filesystems/class.file_status/file_status.cons.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.file_status/file_status.cons.pass.cpp rename to test/std/input.output/filesystems/class.file_status/file_status.cons.pass.cpp index 4c7d5e337..6676c7b7d 100644 --- a/test/std/experimental/filesystem/class.file_status/file_status.cons.pass.cpp +++ b/test/std/input.output/filesystems/class.file_status/file_status.cons.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class file_status diff --git a/test/std/experimental/filesystem/class.file_status/file_status.mods.pass.cpp b/test/std/input.output/filesystems/class.file_status/file_status.mods.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.file_status/file_status.mods.pass.cpp rename to test/std/input.output/filesystems/class.file_status/file_status.mods.pass.cpp index 5492ccde7..4cbf2062a 100644 --- a/test/std/experimental/filesystem/class.file_status/file_status.mods.pass.cpp +++ b/test/std/input.output/filesystems/class.file_status/file_status.mods.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class file_status diff --git a/test/std/experimental/filesystem/class.file_status/file_status.obs.pass.cpp b/test/std/input.output/filesystems/class.file_status/file_status.obs.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.file_status/file_status.obs.pass.cpp rename to test/std/input.output/filesystems/class.file_status/file_status.obs.pass.cpp index 462670fd8..89739b77d 100644 --- a/test/std/experimental/filesystem/class.file_status/file_status.obs.pass.cpp +++ b/test/std/input.output/filesystems/class.file_status/file_status.obs.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class file_status diff --git a/test/std/experimental/filesystem/class.filesystem_error/filesystem_error.members.pass.cpp b/test/std/input.output/filesystems/class.filesystem_error/filesystem_error.members.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.filesystem_error/filesystem_error.members.pass.cpp rename to test/std/input.output/filesystems/class.filesystem_error/filesystem_error.members.pass.cpp index e9b117a79..b7484df5c 100644 --- a/test/std/experimental/filesystem/class.filesystem_error/filesystem_error.members.pass.cpp +++ b/test/std/input.output/filesystems/class.filesystem_error/filesystem_error.members.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class filesystem_error diff --git a/test/std/experimental/filesystem/class.path/path.itr/iterator.pass.cpp b/test/std/input.output/filesystems/class.path/path.itr/iterator.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.path/path.itr/iterator.pass.cpp rename to test/std/input.output/filesystems/class.path/path.itr/iterator.pass.cpp index 0ea672bdf..b7a0383e0 100644 --- a/test/std/experimental/filesystem/class.path/path.itr/iterator.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.itr/iterator.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp index 11bc5dd9b..a02ef18c4 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.append.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.append.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.assign/braced_init.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.assign/braced_init.pass.cpp similarity index 95% rename from test/std/experimental/filesystem/class.path/path.member/path.assign/braced_init.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.assign/braced_init.pass.cpp index bbf331310..fe677c3e6 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.assign/braced_init.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.assign/braced_init.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.assign/copy.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.assign/copy.pass.cpp similarity index 96% rename from test/std/experimental/filesystem/class.path/path.member/path.assign/copy.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.assign/copy.pass.cpp index 8b54be6ed..a0575e649 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.assign/copy.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.assign/copy.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.assign/move.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.path/path.member/path.assign/move.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp index c5cb37fac..71fa47d1b 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.assign/move.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.assign/source.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.assign/source.pass.cpp index 2e064fa48..92eff6e07 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.assign/source.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.assign/source.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp index a2af09412..7791097dc 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.compare.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.compare.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp index 13203d6c6..03d5134fe 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.concat.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.construct/copy.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.construct/copy.pass.cpp similarity index 96% rename from test/std/experimental/filesystem/class.path/path.member/path.construct/copy.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.construct/copy.pass.cpp index 14b4b38c9..69bdb7415 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.construct/copy.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.construct/copy.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.construct/default.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.construct/default.pass.cpp similarity index 95% rename from test/std/experimental/filesystem/class.path/path.member/path.construct/default.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.construct/default.pass.cpp index fddeff989..aa4b03e9b 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.construct/default.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.construct/default.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.construct/move.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.path/path.member/path.construct/move.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp index 16f89d0a2..2e8cce228 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.construct/move.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.construct/source.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.construct/source.pass.cpp index a7c14f3ce..39d63f456 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.construct/source.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.construct/source.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.decompose/empty.fail.cpp b/test/std/input.output/filesystems/class.path/path.member/path.decompose/empty.fail.cpp similarity index 96% rename from test/std/experimental/filesystem/class.path/path.member/path.decompose/empty.fail.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.decompose/empty.fail.cpp index ecc4c0c30..1a722d7a2 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.decompose/empty.fail.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.decompose/empty.fail.cpp @@ -8,7 +8,7 @@ // //===----------------------------------------------------------------------===// -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.decompose/path.decompose.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.decompose/path.decompose.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.path/path.member/path.decompose/path.decompose.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.decompose/path.decompose.pass.cpp index f959e43a3..4eb15cd0b 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.decompose/path.decompose.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.decompose/path.decompose.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_normal.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_normal.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_normal.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_normal.pass.cpp index c897ab60f..3e2fdd08d 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_normal.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_normal.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp index 8b56a19b7..52c577bc8 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.gen/lexically_relative_and_proximate.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp index a757cbb88..93c49a6ab 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/generic_string_alloc.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/named_overloads.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/named_overloads.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.path/path.member/path.generic.obs/named_overloads.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.generic.obs/named_overloads.pass.cpp index 56b2787fb..d41ab619a 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.generic.obs/named_overloads.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/named_overloads.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/clear.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/clear.pass.cpp similarity index 96% rename from test/std/experimental/filesystem/class.path/path.member/path.modifiers/clear.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.modifiers/clear.pass.cpp index 1d697571c..fca642647 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/clear.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/clear.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/make_preferred.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/make_preferred.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.path/path.member/path.modifiers/make_preferred.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.modifiers/make_preferred.pass.cpp index b09806c23..ec914b1bc 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/make_preferred.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/make_preferred.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/remove_filename.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.modifiers/remove_filename.pass.cpp index ec885f15c..b4019e7f2 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/remove_filename.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/remove_filename.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_extension.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/replace_extension.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_extension.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.modifiers/replace_extension.pass.cpp index 2e7d92555..c118b8714 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_extension.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/replace_extension.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_filename.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/replace_filename.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_filename.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.modifiers/replace_filename.pass.cpp index bfb3b6a19..07cd32772 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/replace_filename.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/replace_filename.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/swap.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/swap.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.path/path.member/path.modifiers/swap.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.modifiers/swap.pass.cpp index 3aac1ed60..eecfe4252 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.modifiers/swap.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.modifiers/swap.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/c_str.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.native.obs/c_str.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.path/path.member/path.native.obs/c_str.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.native.obs/c_str.pass.cpp index f907410a8..e035764d2 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/c_str.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.native.obs/c_str.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/named_overloads.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.native.obs/named_overloads.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.path/path.member/path.native.obs/named_overloads.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.native.obs/named_overloads.pass.cpp index 9034ad450..bb0f58cab 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/named_overloads.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.native.obs/named_overloads.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/native.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.native.obs/native.pass.cpp similarity index 96% rename from test/std/experimental/filesystem/class.path/path.member/path.native.obs/native.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.native.obs/native.pass.cpp index 35ea49346..ca02b8680 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/native.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.native.obs/native.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/operator_string.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.native.obs/operator_string.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.path/path.member/path.native.obs/operator_string.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.native.obs/operator_string.pass.cpp index 9aa1b14c8..4f5f77df4 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/operator_string.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.native.obs/operator_string.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/string_alloc.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.native.obs/string_alloc.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.path/path.member/path.native.obs/string_alloc.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.native.obs/string_alloc.pass.cpp index 503c29c32..744ad4df8 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.native.obs/string_alloc.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.native.obs/string_alloc.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.member/path.query/tested_in_path_decompose.pass.cpp b/test/std/input.output/filesystems/class.path/path.member/path.query/tested_in_path_decompose.pass.cpp similarity index 96% rename from test/std/experimental/filesystem/class.path/path.member/path.query/tested_in_path_decompose.pass.cpp rename to test/std/input.output/filesystems/class.path/path.member/path.query/tested_in_path_decompose.pass.cpp index 9cf37d4cd..be662fcb1 100644 --- a/test/std/experimental/filesystem/class.path/path.member/path.query/tested_in_path_decompose.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.member/path.query/tested_in_path_decompose.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.nonmember/append_op.pass.cpp b/test/std/input.output/filesystems/class.path/path.nonmember/append_op.pass.cpp similarity index 96% rename from test/std/experimental/filesystem/class.path/path.nonmember/append_op.pass.cpp rename to test/std/input.output/filesystems/class.path/path.nonmember/append_op.pass.cpp index 3648da57a..09498bf21 100644 --- a/test/std/experimental/filesystem/class.path/path.nonmember/append_op.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.nonmember/append_op.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // path operator/(path const&, path const&); diff --git a/test/std/experimental/filesystem/class.path/path.nonmember/comparison_ops_tested_elsewhere.pass.cpp b/test/std/input.output/filesystems/class.path/path.nonmember/comparison_ops_tested_elsewhere.pass.cpp similarity index 100% rename from test/std/experimental/filesystem/class.path/path.nonmember/comparison_ops_tested_elsewhere.pass.cpp rename to test/std/input.output/filesystems/class.path/path.nonmember/comparison_ops_tested_elsewhere.pass.cpp diff --git a/test/std/experimental/filesystem/class.path/path.nonmember/hash_value_tested_elswhere.pass.cpp b/test/std/input.output/filesystems/class.path/path.nonmember/hash_value_tested_elswhere.pass.cpp similarity index 100% rename from test/std/experimental/filesystem/class.path/path.nonmember/hash_value_tested_elswhere.pass.cpp rename to test/std/input.output/filesystems/class.path/path.nonmember/hash_value_tested_elswhere.pass.cpp diff --git a/test/std/experimental/filesystem/class.path/path.nonmember/path.factory.pass.cpp b/test/std/input.output/filesystems/class.path/path.nonmember/path.factory.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.path/path.nonmember/path.factory.pass.cpp rename to test/std/input.output/filesystems/class.path/path.nonmember/path.factory.pass.cpp index 5d9194b4e..96b8286d5 100644 --- a/test/std/experimental/filesystem/class.path/path.nonmember/path.factory.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.nonmember/path.factory.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // template // path u8path(Source const&); diff --git a/test/std/experimental/filesystem/class.path/path.nonmember/path.io.pass.cpp b/test/std/input.output/filesystems/class.path/path.nonmember/path.io.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.path/path.nonmember/path.io.pass.cpp rename to test/std/input.output/filesystems/class.path/path.nonmember/path.io.pass.cpp index 58e333aad..7902289ed 100644 --- a/test/std/experimental/filesystem/class.path/path.nonmember/path.io.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.nonmember/path.io.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.nonmember/path.io.unicode_bug.pass.cpp b/test/std/input.output/filesystems/class.path/path.nonmember/path.io.unicode_bug.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.path/path.nonmember/path.io.unicode_bug.pass.cpp rename to test/std/input.output/filesystems/class.path/path.nonmember/path.io.unicode_bug.pass.cpp index ff622532e..65be19fdc 100644 --- a/test/std/experimental/filesystem/class.path/path.nonmember/path.io.unicode_bug.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.nonmember/path.io.unicode_bug.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.path/path.nonmember/swap.pass.cpp b/test/std/input.output/filesystems/class.path/path.nonmember/swap.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.path/path.nonmember/swap.pass.cpp rename to test/std/input.output/filesystems/class.path/path.nonmember/swap.pass.cpp index 4f7b93a05..554b5129c 100644 --- a/test/std/experimental/filesystem/class.path/path.nonmember/swap.pass.cpp +++ b/test/std/input.output/filesystems/class.path/path.nonmember/swap.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // void swap(path& lhs, path& rhs) noexcept; diff --git a/test/std/experimental/filesystem/class.path/synop.pass.cpp b/test/std/input.output/filesystems/class.path/synop.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.path/synop.pass.cpp rename to test/std/input.output/filesystems/class.path/synop.pass.cpp index 3ed0a8f19..875f92fb6 100644 --- a/test/std/experimental/filesystem/class.path/synop.pass.cpp +++ b/test/std/input.output/filesystems/class.path/synop.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp index 15cf50569..40ce491b7 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class recursive_directory_iterator diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp index ebe4c87d0..00c8c35fc 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/copy_assign.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class recursive_directory_iterator diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp index 29a86258d..e02d6679c 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class directory_iterator diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp index d27194abe..9b239c6bf 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/depth.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class recursive_directory_iterator diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp index e385624bc..799494f1b 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/disable_recursion_pending.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class recursive_directory_iterator diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp index ad6151881..bfc818924 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class recursive_directory_iterator diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp index 6fe26d5ed..e258c45e3 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class recursive_directory_iterator diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp index fc6d05cb0..61bb8724b 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/move_assign.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class recursive_directory_iterator diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp index 39e0f4f57..fe6ce5ff3 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/pop.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class recursive_directory_iterator diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp index 36453a279..662c11446 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/recursion_pending.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class recursive_directory_iterator diff --git a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp rename to test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp index 8d9f14dfe..04bc2dd1d 100644 --- a/test/std/experimental/filesystem/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp +++ b/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.nonmembers/begin_end.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class recursive_directory_iterator diff --git a/test/std/experimental/filesystem/fs.enum/check_bitmask_types.hpp b/test/std/input.output/filesystems/fs.enum/check_bitmask_types.hpp similarity index 100% rename from test/std/experimental/filesystem/fs.enum/check_bitmask_types.hpp rename to test/std/input.output/filesystems/fs.enum/check_bitmask_types.hpp diff --git a/test/std/experimental/filesystem/fs.enum/enum.copy_options.pass.cpp b/test/std/input.output/filesystems/fs.enum/enum.copy_options.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.enum/enum.copy_options.pass.cpp rename to test/std/input.output/filesystems/fs.enum/enum.copy_options.pass.cpp index 4e3a33ce3..75477309f 100644 --- a/test/std/experimental/filesystem/fs.enum/enum.copy_options.pass.cpp +++ b/test/std/input.output/filesystems/fs.enum/enum.copy_options.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // enum class copy_options; diff --git a/test/std/experimental/filesystem/fs.enum/enum.directory_options.pass.cpp b/test/std/input.output/filesystems/fs.enum/enum.directory_options.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/fs.enum/enum.directory_options.pass.cpp rename to test/std/input.output/filesystems/fs.enum/enum.directory_options.pass.cpp index d866c0b45..db40f6de9 100644 --- a/test/std/experimental/filesystem/fs.enum/enum.directory_options.pass.cpp +++ b/test/std/input.output/filesystems/fs.enum/enum.directory_options.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // enum class directory_options; diff --git a/test/std/experimental/filesystem/fs.enum/enum.file_type.pass.cpp b/test/std/input.output/filesystems/fs.enum/enum.file_type.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/fs.enum/enum.file_type.pass.cpp rename to test/std/input.output/filesystems/fs.enum/enum.file_type.pass.cpp index 6b6e069ff..899ab6820 100644 --- a/test/std/experimental/filesystem/fs.enum/enum.file_type.pass.cpp +++ b/test/std/input.output/filesystems/fs.enum/enum.file_type.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // enum class file_type; diff --git a/test/std/experimental/filesystem/fs.enum/enum.path.format.pass.cpp b/test/std/input.output/filesystems/fs.enum/enum.path.format.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/fs.enum/enum.path.format.pass.cpp rename to test/std/input.output/filesystems/fs.enum/enum.path.format.pass.cpp index 51e3f86ea..d4ec48e84 100644 --- a/test/std/experimental/filesystem/fs.enum/enum.path.format.pass.cpp +++ b/test/std/input.output/filesystems/fs.enum/enum.path.format.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // class path; // enum class format; diff --git a/test/std/experimental/filesystem/fs.enum/enum.perm_options.pass.cpp b/test/std/input.output/filesystems/fs.enum/enum.perm_options.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/fs.enum/enum.perm_options.pass.cpp rename to test/std/input.output/filesystems/fs.enum/enum.perm_options.pass.cpp index c1066b63b..5af504530 100644 --- a/test/std/experimental/filesystem/fs.enum/enum.perm_options.pass.cpp +++ b/test/std/input.output/filesystems/fs.enum/enum.perm_options.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // enum class perm_options; diff --git a/test/std/experimental/filesystem/fs.enum/enum.perms.pass.cpp b/test/std/input.output/filesystems/fs.enum/enum.perms.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.enum/enum.perms.pass.cpp rename to test/std/input.output/filesystems/fs.enum/enum.perms.pass.cpp index 7cd8f6779..9f2e4e214 100644 --- a/test/std/experimental/filesystem/fs.enum/enum.perms.pass.cpp +++ b/test/std/input.output/filesystems/fs.enum/enum.perms.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // enum class perms; diff --git a/test/std/experimental/filesystem/fs.error.report/tested_elsewhere.pass.cpp b/test/std/input.output/filesystems/fs.error.report/tested_elsewhere.pass.cpp similarity index 100% rename from test/std/experimental/filesystem/fs.error.report/tested_elsewhere.pass.cpp rename to test/std/input.output/filesystems/fs.error.report/tested_elsewhere.pass.cpp diff --git a/test/std/experimental/filesystem/fs.filesystem.synopsis/file_time_type.pass.cpp b/test/std/input.output/filesystems/fs.filesystem.synopsis/file_time_type.pass.cpp similarity index 97% rename from test/std/experimental/filesystem/fs.filesystem.synopsis/file_time_type.pass.cpp rename to test/std/input.output/filesystems/fs.filesystem.synopsis/file_time_type.pass.cpp index 1c25450da..157083a30 100644 --- a/test/std/experimental/filesystem/fs.filesystem.synopsis/file_time_type.pass.cpp +++ b/test/std/input.output/filesystems/fs.filesystem.synopsis/file_time_type.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // typedef TrivialClock file_time_type; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.absolute/absolute.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.absolute/absolute.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.absolute/absolute.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.absolute/absolute.pass.cpp index 9b73aedc8..b2a5794a5 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.absolute/absolute.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.absolute/absolute.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // path absolute(const path& p, const path& base=current_path()); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.canonical/canonical.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.canonical/canonical.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp index c9c9128aa..eb10d9816 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.canonical/canonical.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.canonical/canonical.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // path canonical(const path& p); // path canonical(const path& p, error_code& ec); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy/copy.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy/copy.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.copy/copy.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.copy/copy.pass.cpp index ce853b636..ba579d0af 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy/copy.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy/copy.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // void copy(const path& from, const path& to); // void copy(const path& from, const path& to, error_code& ec); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp index 5f023743a..a67b431fb 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool copy_file(const path& from, const path& to); // bool copy_file(const path& from, const path& to, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp index 46b5f2a67..61733d526 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_large.pass.cpp @@ -10,7 +10,7 @@ // UNSUPPORTED: c++98, c++03 // REQUIRES: long_tests -// +// // bool copy_file(const path& from, const path& to); // bool copy_file(const path& from, const path& to, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp index 2530bc9b6..ee4a9ed4b 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_symlink/copy_symlink.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // void copy_symlink(const path& existing_symlink, const path& new_symlink); // void copy_symlink(const path& existing_symlink, const path& new_symlink, diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp index 8afc6102e..6b651dfb0 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directories/create_directories.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool create_directories(const path& p); // bool create_directories(const path& p, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp index 7885c4a54..e73e21ffb 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool create_directory(const path& p); // bool create_directory(const path& p, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp index 2ee55fc4c..f013bbb20 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory/create_directory_with_attributes.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool create_directory(const path& p, const path& attr); // bool create_directory(const path& p, const path& attr, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp index e7cba97dd..f1d9ff041 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_directory_symlink/create_directory_symlink.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // void create_directory_symlink(const path& existing_symlink, const path& new_symlink); // void create_directory_symlink(const path& existing_symlink, const path& new_symlink, diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp index 7dbc705f4..f1ffc74c2 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_hard_link/create_hard_link.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // void create_hard_link(const path& existing_symlink, const path& new_symlink); // void create_hard_link(const path& existing_symlink, const path& new_symlink, diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp index 46519ad77..e69aae186 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.create_symlink/create_symlink.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // void create_symlink(const path& existing_symlink, const path& new_symlink); // void create_symlink(const path& existing_symlink, const path& new_symlink, diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.current_path/current_path.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.current_path/current_path.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.current_path/current_path.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.current_path/current_path.pass.cpp index 82ba91c0f..dd3736e08 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.current_path/current_path.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.current_path/current_path.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // path current_path(); // path current_path(error_code& ec); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp index 3381f64d5..392f66c6d 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.equivalent/equivalent.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool equivalent(path const& lhs, path const& rhs); // bool equivalent(path const& lhs, path const& rhs, std::error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.exists/exists.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.exists/exists.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp index 4b6ed9642..916052b74 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.exists/exists.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool exists(file_status s) noexcept // bool exists(path const& p); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp index c79012d9e..60e0042cf 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.file_size/file_size.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.file_size/file_size.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // uintmax_t file_size(const path& p); // uintmax_t file_size(const path& p, std::error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp index f90e3f772..2e9704a3d 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.hard_lk_ct/hard_link_count.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // uintmax_t hard_link_count(const path& p); // uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp index c27565e5f..36f1d6bbd 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool is_block_file(file_status s) noexcept // bool is_block_file(path const& p); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp index 546881920..b0c3fe542 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool is_character_file(file_status s) noexcept // bool is_character_file(path const& p); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp index 3270fcc80..bb578b9cf 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool is_directory(file_status s) noexcept // bool is_directory(path const& p); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp index ffe60a823..cd4dd1748 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool is_empty(path const& p); // bool is_empty(path const& p, std::error_code& ec); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp index 9c56f7356..3c86dc0e7 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool is_fifo(file_status s) noexcept // bool is_fifo(path const& p); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_other/is_other.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.is_other/is_other.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp index d01268a73..a2134c7c1 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_other/is_other.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool is_other(file_status s) noexcept // bool is_other(path const& p); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp index 96e027d2c..0c3488635 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool is_regular_file(file_status s) noexcept // bool is_regular_file(path const& p); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp index 1593d6a3b..7273c6c2e 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool is_socket(file_status s) noexcept // bool is_socket(path const& p); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp index 97cd0a3d0..e1ac98a80 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool is_symlink(file_status s) noexcept // bool is_symlink(path const& p); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp index 616264d3d..bc77f3f63 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // file_time_type last_write_time(const path& p); // file_time_type last_write_time(const path& p, std::error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.permissions/permissions.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.permissions/permissions.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.permissions/permissions.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.permissions/permissions.pass.cpp index 65d8d7164..cbe2b2d09 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.permissions/permissions.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.permissions/permissions.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // void permissions(const path& p, perms prms, // perm_options opts = perm_options::replace); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.proximate/proximate.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.proximate/proximate.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.proximate/proximate.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.proximate/proximate.pass.cpp index dc89228a7..5f7b30dd6 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.proximate/proximate.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.proximate/proximate.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // path proximate(const path& p, error_code &ec) // path proximate(const path& p, const path& base = current_path()) diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp index 8011da343..43dfec834 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.read_symlink/read_symlink.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // path read_symlink(const path& p); // path read_symlink(const path& p, error_code& ec); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.relative/relative.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.relative/relative.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp index 62bc32a73..e240c6496 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.relative/relative.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.relative/relative.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // path proximate(const path& p, error_code &ec) // path proximate(const path& p, const path& base = current_path()) diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp index 2b5f52c75..37b47f151 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove/remove.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool remove(const path& p); // bool remove(const path& p, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp index 99935f44b..0f015c387 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // uintmax_t remove_all(const path& p); // uintmax_t remove_all(const path& p, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.rename/rename.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.rename/rename.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.rename/rename.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.rename/rename.pass.cpp index f20d73fcc..e2ebdc61f 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.rename/rename.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.rename/rename.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // void rename(const path& old_p, const path& new_p); // void rename(const path& old_p, const path& new_p, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp index 38596cd4c..1a2df47e6 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.resize_file/resize_file.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // void resize_file(const path& p, uintmax_t new_size); // void resize_file(const path& p, uintmax_t new_size, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.space/space.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.space/space.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp index 4f617cd66..2c2e75af6 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.space/space.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.space/space.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // space_info space(const path& p); // space_info space(const path& p, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.status/status.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.status/status.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp index 997f318f7..ab72f2e5d 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.status/status.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // file_status status(const path& p); // file_status status(const path& p, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.status_known/status_known.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.status_known/status_known.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.status_known/status_known.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.status_known/status_known.pass.cpp index ed6733fb6..d74ced643 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.status_known/status_known.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.status_known/status_known.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // bool status_known(file_status s) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp index 9db83fbc3..fac630da1 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // file_status symlink_status(const path& p); // file_status symlink_status(const path& p, error_code& ec) noexcept; diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp similarity index 99% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp index 1942bd8b4..523e429cf 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // path temp_directory_path(); // path temp_directory_path(error_code& ec); diff --git a/test/std/experimental/filesystem/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp b/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp similarity index 98% rename from test/std/experimental/filesystem/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp rename to test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp index b4cb81d5b..0fe058ffd 100644 --- a/test/std/experimental/filesystem/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp +++ b/test/std/input.output/filesystems/fs.op.funcs/fs.op.weakly_canonical/weakly_canonical.pass.cpp @@ -9,7 +9,7 @@ // UNSUPPORTED: c++98, c++03 -// +// // path weakly_canonical(const path& p); // path weakly_canonical(const path& p, error_code& ec); diff --git a/test/std/input.output/filesystems/fs.req.macros/feature_macro.pass.cpp b/test/std/input.output/filesystems/fs.req.macros/feature_macro.pass.cpp new file mode 100644 index 000000000..071fa800c --- /dev/null +++ b/test/std/input.output/filesystems/fs.req.macros/feature_macro.pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// #define __cpp_lib_filesystem 201703L + +#include +#include "test_macros.h" + +#if TEST_STD_VER >= 17 +#ifndef __cpp_lib_filesystem +#error Filesystem feature test macro is not defined (__cpp_lib_filesystem) +#elif __cpp_lib_filesystem != 201703L +#error Filesystem feature test macro has an incorrect value (__cpp_lib_filesystem) +#endif +#else // TEST_STD_VER < 17 +#ifdef __cpp_lib_filesystem +#error Filesystem feature test macro should not be defined before C++17 +#endif +#endif + +int main() { } diff --git a/test/std/input.output/filesystems/fs.req.namespace/namespace.fail.cpp b/test/std/input.output/filesystems/fs.req.namespace/namespace.fail.cpp new file mode 100644 index 000000000..c61bb2e12 --- /dev/null +++ b/test/std/input.output/filesystems/fs.req.namespace/namespace.fail.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// REQUIRES: c++98 || c++03 || c++11 || c++14 + +// + +// namespace std::filesystem + +#include +#include "test_macros.h" + +using namespace std::filesystem; + +#if TEST_STD_VER >= 11 +// expected-error@-3 {{no namespace named 'filesystem' in namespace 'std';}} +#else +// expected-error@-5 {{expected namespace name}} +#endif + +int main() { + +} diff --git a/test/std/input.output/filesystems/fs.req.namespace/namespace.pass.cpp b/test/std/input.output/filesystems/fs.req.namespace/namespace.pass.cpp new file mode 100644 index 000000000..557de3488 --- /dev/null +++ b/test/std/input.output/filesystems/fs.req.namespace/namespace.pass.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// namespace std::filesystem + +#include +#include + +using namespace std::filesystem; + +int main() { + static_assert(std::is_same< + path, + std::filesystem::path + >::value, ""); +} diff --git a/test/std/experimental/filesystem/lit.local.cfg b/test/std/input.output/filesystems/lit.local.cfg similarity index 100% rename from test/std/experimental/filesystem/lit.local.cfg rename to test/std/input.output/filesystems/lit.local.cfg diff --git a/test/support/filesystem_include.hpp b/test/support/filesystem_include.hpp index 228e710f3..731532a7b 100644 --- a/test/support/filesystem_include.hpp +++ b/test/support/filesystem_include.hpp @@ -1,18 +1,13 @@ #ifndef TEST_SUPPORT_FILESYSTEM_INCLUDE_HPP #define TEST_SUPPORT_FILESYSTEM_INCLUDE_HPP -#include -// Test against std::filesystem for STL's other than libc++ -#ifndef _LIBCPP_VERSION -#define TEST_INCLUDE_STD_FILESYSTEM -#endif - -#ifdef TEST_INCLUDE_STD_FILESYSTEM #include -namespace fs = std::filesystem; +#include "test_macros.h" + +#if defined(_LIBCPP_VERSION) && TEST_STD_VER < 17 +namespace fs = std::__fs::filesystem; #else -#include -namespace fs = std::experimental::filesystem; +namespace fs = std::filesystem; #endif #endif diff --git a/utils/libcxx/test/config.py b/utils/libcxx/test/config.py index 34753be84..6542ceb6f 100644 --- a/utils/libcxx/test/config.py +++ b/utils/libcxx/test/config.py @@ -720,13 +720,9 @@ class Configuration(object): enable_fs = self.get_lit_bool('enable_filesystem', default=False) if not enable_fs: return - enable_experimental = self.get_lit_bool('enable_experimental', default=False) - if not enable_experimental: - self.lit_config.fatal( - 'filesystem is enabled but libc++experimental.a is not.') self.config.available_features.add('c++filesystem') static_env = os.path.join(self.libcxx_src_root, 'test', 'std', - 'experimental', 'filesystem', 'Inputs', 'static_test_env') + 'input.output', 'filesystems', 'Inputs', 'static_test_env') static_env = os.path.realpath(static_env) assert os.path.isdir(static_env) self.cxx.compile_flags += ['-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="%s"' % static_env] @@ -821,6 +817,10 @@ class Configuration(object): if libcxx_experimental: self.config.available_features.add('c++experimental') self.cxx.link_flags += ['-lc++experimental'] + libcxx_fs = self.get_lit_bool('enable_filesystem', default=False) + if libcxx_fs: + self.config.available_features.add('c++fs') + self.cxx.link_flags += ['-lc++fs'] if self.link_shared: self.cxx.link_flags += ['-lc++'] else: diff --git a/www/cxx1z_status.html b/www/cxx1z_status.html index 3d826acf3..de8caa87f 100644 --- a/www/cxx1z_status.html +++ b/www/cxx1z_status.html @@ -83,7 +83,7 @@ P0024R2LWGThe Parallelism TS Should be StandardizedJacksonville P0226R1LWGMathematical Special Functions for C++17Jacksonville - P0220R1LWGAdopt Library Fundamentals V1 TS Components for C++17JacksonvilleIn Progress + P0220R1LWGAdopt Library Fundamentals V1 TS Components for C++17JacksonvilleComplete7.0 P0218R1LWGAdopt the File System TS for C++17JacksonvilleIn Progress P0033R1LWGRe-enabling shared_from_thisJacksonvilleComplete3.9 P0005R4LWGAdopt not_fn from Library Fundamentals 2 for C++17JacksonvilleComplete3.9 @@ -443,7 +443,7 @@ 2778basic_string_view is missing constexprIssaquahComplete 2260Missing requirement for Allocator::pointerKona - 2676Provide filesystem::path overloads for File-based streamsKona + 2676Provide filesystem::path overloads for File-based streamsKonaComplete 2768any_cast and move semanticsKonaComplete 2769Redundant const in the return type of any_cast(const any&)KonaComplete 2781Contradictory requirements for std::function and std::reference_wrapperKonaComplete -- GitLab From 789c3724564b1592fc1f0f6235dfc9195664febd Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 27 Jul 2018 03:16:02 +0000 Subject: [PATCH 102/495] Correctly mark the Filesystem status as complete. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338094 91177308-0d34-0410-b5e6-96231b3b80d8 --- www/cxx1z_status.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/cxx1z_status.html b/www/cxx1z_status.html index de8caa87f..dc3528373 100644 --- a/www/cxx1z_status.html +++ b/www/cxx1z_status.html @@ -83,8 +83,8 @@ P0024R2LWGThe Parallelism TS Should be StandardizedJacksonville P0226R1LWGMathematical Special Functions for C++17Jacksonville - P0220R1LWGAdopt Library Fundamentals V1 TS Components for C++17JacksonvilleComplete7.0 - P0218R1LWGAdopt the File System TS for C++17JacksonvilleIn Progress + P0220R1LWGAdopt Library Fundamentals V1 TS Components for C++17JacksonvilleIn Progress + P0218R1LWGAdopt the File System TS for C++17JacksonvilleComplete7.0 P0033R1LWGRe-enabling shared_from_thisJacksonvilleComplete3.9 P0005R4LWGAdopt not_fn from Library Fundamentals 2 for C++17JacksonvilleComplete3.9 P0152R1LWGconstexpr atomic::is_always_lock_freeJacksonvilleComplete3.9 -- GitLab From 0be5527dc09eb9148bed9d415a6bf37b670ef95d Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 27 Jul 2018 03:42:58 +0000 Subject: [PATCH 103/495] Attempt to unbreak *all the bots* The bots were failing to build the cxx_filesystem target, so the tests were failing. Though this does lead me to wonder how it was ever working with c++experimental. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338095 91177308-0d34-0410-b5e6-96231b3b80d8 --- CMakeLists.txt | 4 ++-- include/CMakeLists.txt | 1 + lib/CMakeLists.txt | 10 ++++++---- test/CMakeLists.txt | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cd4786ec6..39ff0a29d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ set(ENABLE_FILESYSTEM_DEFAULT ${LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY}) if (WIN32) set(ENABLE_FILESYSTEM_DEFAULT OFF) endif() -option(LIBCXX_ENABLE_FILESYSTEM "Build filesystem as part of libc++experimental.a" +option(LIBCXX_ENABLE_FILESYSTEM "Build filesystem as part of libc++fs.a" ${ENABLE_FILESYSTEM_DEFAULT}) option(LIBCXX_INCLUDE_TESTS "Build the libc++ tests." ${LLVM_INCLUDE_TESTS}) @@ -109,7 +109,7 @@ cmake_dependent_option(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY "LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY;LIBCXX_INSTALL_LIBRARY" OFF) cmake_dependent_option(LIBCXX_INSTALL_FILESYSTEM_LIBRARY "Install libc++fs.a" ON - "LIBCXX_ENABLE_FILESYSTEM_LIBRARY;LIBCXX_INSTALL_LIBRARY" OFF) + "LIBCXX_ENABLE_FILESYSTEM;LIBCXX_INSTALL_LIBRARY" OFF) if (FUCHSIA) set(DEFAULT_ABI_VERSION 2) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index f4f894154..c5e92e4c4 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -93,6 +93,7 @@ set(files ext/__hash ext/hash_map ext/hash_set + filesystem float.h forward_list fstream diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index a40d217dc..322fce43f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -288,10 +288,6 @@ if (LIBCXX_ENABLE_STATIC) endif() endif() -# Add a meta-target for both libraries. -add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_BUILD_TARGETS}) - - if (LIBCXX_ENABLE_FILESYSTEM) set(LIBCXX_FILESYSTEM_SOURCES ../src/filesystem/operations.cpp @@ -322,6 +318,7 @@ if (LIBCXX_ENABLE_FILESYSTEM) COMPILE_FLAGS "${filesystem_flags}" OUTPUT_NAME "c++fs" ) + list(APPEND LIBCXX_BUILD_TARGETS cxx_filesystem) endif() @@ -344,9 +341,14 @@ if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) COMPILE_FLAGS "${experimental_flags}" OUTPUT_NAME "c++experimental" ) + list(APPEND LIBCXX_BUILD_TARGETS cxx_experimental) endif() +# Add a meta-target for both libraries. +add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_BUILD_TARGETS}) + + if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY) file(GLOB LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES ../test/support/external_threads.cpp) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 45dc34ac2..6492949d9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -105,7 +105,7 @@ if (LIBCXX_CONFIGURE_IDE) ${LIBCXX_TESTS} ${LIBCXX_TEST_HEADERS} ${LIBCXX_HEADERS}) add_dependencies(libcxx_test_objects cxx) - set(STATIC_ROOT ${LIBCXX_SOURCE_DIR}/test/std/experimental/filesystem/Inputs/static_test_env) + set(STATIC_ROOT ${LIBCXX_SOURCE_DIR}/test/std/input.output/filesystems/Inputs/static_test_env) add_definitions(-DLIBCXX_FILESYSTEM_STATIC_TEST_ROOT="${STATIC_ROOT}") set(DYNAMIC_ROOT ${LIBCXX_BINARY_DIR}/test/filesystem/Output/dynamic_env) -- GitLab From bc3f4035c39e6b86262a4e87253fad0281c4e89a Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 27 Jul 2018 03:47:46 +0000 Subject: [PATCH 104/495] Add libc++fs to the test deps, and not to the target 'cxx'. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338096 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CMakeLists.txt | 10 +++------- test/CMakeLists.txt | 5 ++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 322fce43f..e068edc8a 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -288,6 +288,9 @@ if (LIBCXX_ENABLE_STATIC) endif() endif() +# Add a meta-target for both libraries. +add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_BUILD_TARGETS}) + if (LIBCXX_ENABLE_FILESYSTEM) set(LIBCXX_FILESYSTEM_SOURCES ../src/filesystem/operations.cpp @@ -318,7 +321,6 @@ if (LIBCXX_ENABLE_FILESYSTEM) COMPILE_FLAGS "${filesystem_flags}" OUTPUT_NAME "c++fs" ) - list(APPEND LIBCXX_BUILD_TARGETS cxx_filesystem) endif() @@ -341,14 +343,8 @@ if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) COMPILE_FLAGS "${experimental_flags}" OUTPUT_NAME "c++experimental" ) - list(APPEND LIBCXX_BUILD_TARGETS cxx_experimental) endif() - -# Add a meta-target for both libraries. -add_custom_target(cxx DEPENDS cxx-headers ${LIBCXX_BUILD_TARGETS}) - - if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY) file(GLOB LIBCXX_EXTERNAL_THREADING_SUPPORT_SOURCES ../test/support/external_threads.cpp) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6492949d9..f8442460a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -58,7 +58,10 @@ set(AUTO_GEN_COMMENT "## Autogenerated by libcxx configuration.\n# Do not edit!" set(LIBCXX_TEST_DEPS "") if (LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY) - set(LIBCXX_TEST_DEPS cxx_experimental) + 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) -- GitLab From 7e850a8da4f7a653733f9183c3623354265251b7 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 27 Jul 2018 06:12:46 +0000 Subject: [PATCH 105/495] Move Filesystem namespace definition out of a clang specific ifdef block. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338103 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__config | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/include/__config b/include/__config index 4b17fb5e7..139c19971 100644 --- a/include/__config +++ b/include/__config @@ -474,19 +474,6 @@ namespace std { } } -#if _LIBCPP_STD_VER >= 17 -#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ - _LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem { -#else -#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ - _LIBCPP_BEGIN_NAMESPACE_STD namespace __fs { namespace filesystem { -#endif - -#define _LIBCPP_END_NAMESPACE_FILESYSTEM \ - _LIBCPP_END_NAMESPACE_STD } } - -#define _VSTD_FS _VSTD::__fs::filesystem - #if !defined(_LIBCPP_HAS_NO_ASAN) && !__has_feature(address_sanitizer) #define _LIBCPP_HAS_NO_ASAN #endif @@ -659,6 +646,20 @@ namespace std { #endif // _LIBCPP_COMPILER_[CLANG|GCC|MSVC|IBM] +#if _LIBCPP_STD_VER >= 17 +#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ + _LIBCPP_BEGIN_NAMESPACE_STD inline namespace __fs { namespace filesystem { +#else +#define _LIBCPP_BEGIN_NAMESPACE_FILESYSTEM \ + _LIBCPP_BEGIN_NAMESPACE_STD namespace __fs { namespace filesystem { +#endif + +#define _LIBCPP_END_NAMESPACE_FILESYSTEM \ + _LIBCPP_END_NAMESPACE_STD } } + +#define _VSTD_FS _VSTD::__fs::filesystem + + #if defined(_LIBCPP_OBJECT_FORMAT_COFF) #ifdef _DLL -- GitLab From 67fff22b9a92dd24521a91f97266f6b56ab16d7b Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Fri, 27 Jul 2018 12:46:03 +0000 Subject: [PATCH 106/495] [libc++] Introduce _LIBCPP_HIDE_FROM_ABI to replace _LIBCPP_INLINE_VISIBILITY Summary: This commit introduces a new macro, _LIBCPP_HIDE_FROM_ABI, whose goal is to mark functions that shouldn't be part of libc++'s ABI. It marks the functions as being hidden for dylib visibility purposes, and as having internal linkage using Clang's __attribute__((internal_linkage)) when available, and __always_inline__ otherwise. It replaces _LIBCPP_INLINE_VISIBILITY, which was always using __always_inline__ to achieve similar goals, but suffered from debuggability and code size problems. The full proposal, along with more background information, can be found here: http://lists.llvm.org/pipermail/cfe-dev/2018-July/058419.html This commit does not rename uses of _LIBCPP_INLINE_VISIBILITY to _LIBCPP_HIDE_FROM_ABI: this wide reaching but mechanical change can be done later when we've confirmed we're happy with the new macro. In the future, it would be nice if we could optionally allow dropping any internal_linkage or __always_inline__ attribute, which could result in code size improvements. However, this is currently impossible for reasons explained here: http://lists.llvm.org/pipermail/cfe-dev/2018-July/058450.html Reviewers: EricWF, dexonsmith, mclow.lists Subscribers: christof, dexonsmith, llvm-commits, mclow.lists Differential Revision: https://reviews.llvm.org/D49240 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338122 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/DesignDocs/VisibilityMacros.rst | 18 +++++++++++++++++- include/__config | 27 +++++++++++++++++++-------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/docs/DesignDocs/VisibilityMacros.rst b/docs/DesignDocs/VisibilityMacros.rst index 69a09974a..878566ea0 100644 --- a/docs/DesignDocs/VisibilityMacros.rst +++ b/docs/DesignDocs/VisibilityMacros.rst @@ -40,7 +40,7 @@ Visibility Macros this macro therefore expands to `__declspec(dllexport)` when building the library and has an empty definition otherwise. -**_LIBCPP_INLINE_VISIBILITY** +**_LIBCPP_HIDE_FROM_ABI** Mark a function as not being part of the ABI of any final linked image that uses it, and also as being internal to each TU that uses that function. In other words, the address of a function marked with this attribute is not @@ -155,6 +155,22 @@ Visibility Macros versioning namespace. This allows throwing and catching some exception types between libc++ and libstdc++. +**_LIBCPP_INTERNAL_LINKAGE** + Mark the affected entity as having internal linkage (i.e. the `static` + keyword in C). This is only a best effort: when the `internal_linkage` + attribute is not available, we fall back to forcing the function to be + inlined, which approximates internal linkage since an externally visible + symbol is never generated for that function. This is an internal macro + used as an implementation detail by other visibility macros. Never mark + a function or a class with this macro directly. + +**_LIBCPP_ALWAYS_INLINE** + Forces inlining of the function it is applied to. For visibility purposes, + this macro is used to make sure that an externally visible symbol is never + generated in an object file when the `internal_linkage` attribute is not + available. This is an internal macro used by other visibility macros, and + it should not be used directly. + Links ===== diff --git a/include/__config b/include/__config index 139c19971..c01ac12be 100644 --- a/include/__config +++ b/include/__config @@ -491,6 +491,8 @@ namespace std { #define _LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS #endif +#define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) + #elif defined(_LIBCPP_COMPILER_GCC) #define _ALIGNAS(x) __attribute__((__aligned__(x))) @@ -582,6 +584,8 @@ namespace std { #define _LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS #endif +#define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) + #elif defined(_LIBCPP_COMPILER_MSVC) #define _LIBCPP_TOSTRING2(x) #x @@ -614,6 +618,8 @@ namespace std { #define _LIBCPP_HAS_NO_ASAN +#define _LIBCPP_ALWAYS_INLINE __forceinline + #elif defined(_LIBCPP_COMPILER_IBM) #define _ALIGNAS(x) __attribute__((__aligned__(x))) @@ -644,6 +650,8 @@ namespace std { #define _LIBCPP_HAS_NO_ASAN +#define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) + #endif // _LIBCPP_COMPILER_[CLANG|GCC|MSVC|IBM] #if _LIBCPP_STD_VER >= 17 @@ -695,10 +703,8 @@ namespace std { #define _LIBCPP_ENUM_VIS #if defined(_LIBCPP_COMPILER_MSVC) -# define _LIBCPP_INLINE_VISIBILITY __forceinline # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __forceinline #else -# define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__always_inline__)) # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__ ((__always_inline__)) #endif @@ -785,14 +791,19 @@ namespace std { #define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS #endif -#ifndef _LIBCPP_INLINE_VISIBILITY -# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) -# define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__)) -# else -# define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__always_inline__)) -# endif +#if __has_attribute(internal_linkage) +# define _LIBCPP_INTERNAL_LINKAGE __attribute__ ((internal_linkage)) +#else +# define _LIBCPP_INTERNAL_LINKAGE _LIBCPP_ALWAYS_INLINE #endif +#ifndef _LIBCPP_HIDE_FROM_ABI +# define _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDDEN _LIBCPP_INTERNAL_LINKAGE +#endif + +// Just so we can migrate to _LIBCPP_HIDE_FROM_ABI gradually. +#define _LIBCPP_INLINE_VISIBILITY _LIBCPP_HIDE_FROM_ABI + #ifndef _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) # define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__((__visibility__("default"), __always_inline__)) -- GitLab From 8634f6fcca8961d4a7db9dedaebf2ce216cd0592 Mon Sep 17 00:00:00 2001 From: Jordan Rupprecht Date: Fri, 27 Jul 2018 20:02:58 +0000 Subject: [PATCH 107/495] [libc++] Exclude posix_l/strtonum fallback inclusion for newlib > 2.4 Summary: [libc++] Exclude posix_l/strtonum fallback inclusion for newlib > 2.4 r338122 changed the linkage of some methods which revealed an existing ODR violation, e.g.: projects/libcxx/include/support/xlocale/__posix_l_fallback.h:83:38: error: 'internal_linkage' attribute does not appear on the first declaration of 'iswcntrl_l' inline _LIBCPP_INLINE_VISIBILITY int iswcntrl_l(wint_t c, locale_t) { ^ lib/include/wctype.h:55:12: note: previous definition is here extern int iswcntrl_l (wint_t, locale_t); These were added to newlib in 2.4 [1] [2], so move them to the already existing include guard. [1] https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=commit;h=238455adfab4f8070ac65400aac22bb8a9e502fc [2] https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=commit;h=8493c1631643fada62384768408852bc0fa6ff44 Reviewers: ldionne, rsmith, EricWF Subscribers: christof, cfe-commits Differential Revision: https://reviews.llvm.org/D49927 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338157 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/support/newlib/xlocale.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/support/newlib/xlocale.h b/include/support/newlib/xlocale.h index 4b7e9b749..09f9e3987 100644 --- a/include/support/newlib/xlocale.h +++ b/include/support/newlib/xlocale.h @@ -19,9 +19,9 @@ #if !defined(__NEWLIB__) || __NEWLIB__ < 2 || \ __NEWLIB__ == 2 && __NEWLIB_MINOR__ < 5 #include -#endif #include #include +#endif #endif // _NEWLIB_VERSION -- GitLab From 373299533a3158f7180f9bf5605e1477830ccaa3 Mon Sep 17 00:00:00 2001 From: Tim Shen Date: Mon, 30 Jul 2018 21:23:13 +0000 Subject: [PATCH 108/495] [libcxx] implement ABI for Clang/GCC vector extension, constructors, copy_from and copy_to. Summary: This patch adds a new macro _LIBCPP_HAS_NO_VECTOR_EXTENSION for detecting whether a vector extension (\_\_attribute\_\_((vector_size(num_bytes)))) is available. On the top of that, this patch implements the following API: * all constructors * operator[] * copy_from * copy_to It also defines simd_abi::native to use vector extension, if available. In GCC and Clang, certain values with vector extension are passed by registers, instead of memory. Based on D41148. Reviewers: mclow.lists, EricWF Subscribers: cfe-commits, MaskRay, lichray, sanjoy Differential Revision: https://reviews.llvm.org/D41376 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338309 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__config | 4 + include/experimental/__config | 7 + include/experimental/simd | 377 +++++++++++++++--- .../simd/simd.abi/vector_extension.pass.cpp | 67 ++++ .../simd/simd.access/default.pass.cpp | 217 ++++++++++ .../simd/simd.casts/simd_cast.pass.cpp | 38 +- .../simd/simd.casts/static_simd_cast.pass.cpp | 27 +- .../simd/simd.cons/broadcast.pass.cpp | 38 +- .../simd/simd.cons/default.pass.cpp | 28 ++ .../simd/simd.cons/generator.pass.cpp | 73 +++- .../experimental/simd/simd.cons/load.pass.cpp | 118 ++++++ .../experimental/simd/simd.mem/load.pass.cpp | 122 ++++++ .../experimental/simd/simd.mem/store.pass.cpp | 95 +++++ .../simd/simd.traits/abi_for_size.pass.cpp | 18 +- .../simd/simd.traits/is_abi_tag.pass.cpp | 180 +++++---- .../simd/simd.traits/is_simd.pass.cpp | 216 +++++----- .../simd.traits/is_simd_flag_type.pass.cpp | 58 ++- .../simd/simd.traits/is_simd_mask.pass.cpp | 239 ++++++----- 18 files changed, 1477 insertions(+), 445 deletions(-) create mode 100644 test/std/experimental/simd/simd.abi/vector_extension.pass.cpp create mode 100644 test/std/experimental/simd/simd.access/default.pass.cpp create mode 100644 test/std/experimental/simd/simd.cons/default.pass.cpp create mode 100644 test/std/experimental/simd/simd.cons/load.pass.cpp create mode 100644 test/std/experimental/simd/simd.mem/load.pass.cpp create mode 100644 test/std/experimental/simd/simd.mem/store.pass.cpp diff --git a/include/__config b/include/__config index c01ac12be..bba7f53ba 100644 --- a/include/__config +++ b/include/__config @@ -620,6 +620,8 @@ namespace std { #define _LIBCPP_ALWAYS_INLINE __forceinline +#define _LIBCPP_HAS_NO_VECTOR_EXTENSION + #elif defined(_LIBCPP_COMPILER_IBM) #define _ALIGNAS(x) __attribute__((__aligned__(x))) @@ -652,6 +654,8 @@ namespace std { #define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) +#define _LIBCPP_HAS_NO_VECTOR_EXTENSION + #endif // _LIBCPP_COMPILER_[CLANG|GCC|MSVC|IBM] #if _LIBCPP_STD_VER >= 17 diff --git a/include/experimental/__config b/include/experimental/__config index 55ae31b8a..c6f177620 100644 --- a/include/experimental/__config +++ b/include/experimental/__config @@ -64,4 +64,11 @@ #define _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI \ } _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD +// TODO: support more targets +#if defined(__AVX__) +#define _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES 32 +#else +#define _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES 16 +#endif + #endif diff --git a/include/experimental/simd b/include/experimental/simd index 4876ccb82..2cc0d8deb 100644 --- a/include/experimental/simd +++ b/include/experimental/simd @@ -651,6 +651,7 @@ public: */ #include +#include #include #include #include @@ -664,23 +665,241 @@ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD enum class _StorageKind { _Scalar, _Array, + _VecExt, }; template <_StorageKind __kind, int _Np> struct __simd_abi {}; template -struct __simd_storage_traits {}; +class __simd_storage {}; template -struct __simd_storage_traits<_Tp, - __simd_abi<_StorageKind::_Array, __num_element>> { - using type = std::array<_Tp, __num_element>; +class __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> { + std::array<_Tp, __num_element> __storage_; + + template + friend struct simd; + + template + friend struct simd_mask; + +public: + _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; + void __set(size_t __index, _Tp __val) noexcept { + __storage_[__index] = __val; + } }; template -struct __simd_storage_traits<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> { - using type = _Tp; +class __simd_storage<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> { + _Tp __storage_; + + template + friend struct simd; + + template + friend struct simd_mask; + +public: + _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; }; + void __set(size_t __index, _Tp __val) noexcept { + (&__storage_)[__index] = __val; + } +}; + +#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION + +constexpr size_t __floor_pow_of_2(size_t __val) { + return ((__val - 1) & __val) == 0 ? __val + : __floor_pow_of_2((__val - 1) & __val); +} + +constexpr size_t __ceil_pow_of_2(size_t __val) { + return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1; +} + +template +struct __vec_ext_traits { +#if !defined(_LIBCPP_COMPILER_CLANG) + typedef _Tp type __attribute__((vector_size(__ceil_pow_of_2(__bytes)))); +#endif +}; + +#if defined(_LIBCPP_COMPILER_CLANG) +#define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \ + template <> \ + struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \ + using type = \ + _TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT))); \ + } + +#define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE) \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 32); + +_LIBCPP_SPECIALIZE_VEC_EXT_32(char); +_LIBCPP_SPECIALIZE_VEC_EXT_32(char16_t); +_LIBCPP_SPECIALIZE_VEC_EXT_32(char32_t); +_LIBCPP_SPECIALIZE_VEC_EXT_32(wchar_t); +_LIBCPP_SPECIALIZE_VEC_EXT_32(signed char); +_LIBCPP_SPECIALIZE_VEC_EXT_32(signed short); +_LIBCPP_SPECIALIZE_VEC_EXT_32(signed int); +_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long); +_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long long); +_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned char); +_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned short); +_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned int); +_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long); +_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long long); +_LIBCPP_SPECIALIZE_VEC_EXT_32(float); +_LIBCPP_SPECIALIZE_VEC_EXT_32(double); +_LIBCPP_SPECIALIZE_VEC_EXT_32(long double); + +#undef _LIBCPP_SPECIALIZE_VEC_EXT_32 +#undef _LIBCPP_SPECIALIZE_VEC_EXT +#endif + +template +class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> { + using _StorageType = + typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type; + + _StorageType __storage_; + + template + friend struct simd; + + template + friend struct simd_mask; + +public: + _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; + void __set(size_t __index, _Tp __val) noexcept { + __storage_[__index] = __val; + } +}; + +#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION + +template +class __simd_reference { + static_assert(std::is_same<_Vp, _Tp>::value, ""); + + template + friend struct simd; + + template + friend struct simd_mask; + + __simd_storage<_Tp, _Abi>* __ptr_; + size_t __index_; + + __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) + : __ptr_(__ptr), __index_(__index) {} + + __simd_reference(const __simd_reference&) = default; + +public: + __simd_reference() = delete; + __simd_reference& operator=(const __simd_reference&) = delete; + + operator _Vp() const { return __ptr_->__get(__index_); } + + __simd_reference operator=(_Vp __value) && { + __ptr_->__set(__index_, __value); + return *this; + } + + __simd_reference operator++() && { + return std::move(*this) = __ptr_->__get(__index_) + 1; + } + + _Vp operator++(int) && { + auto __val = __ptr_->__get(__index_); + __ptr_->__set(__index_, __val + 1); + return __val; + } + + __simd_reference operator--() && { + return std::move(*this) = __ptr_->__get(__index_) - 1; + } + + _Vp operator--(int) && { + auto __val = __ptr_->__get(__index_); + __ptr_->__set(__index_, __val - 1); + return __val; + } + + __simd_reference operator+=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) + __value; + } + + __simd_reference operator-=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) - __value; + } + + __simd_reference operator*=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) * __value; + } + + __simd_reference operator/=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) / __value; + } + + __simd_reference operator%=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) % __value; + } + + __simd_reference operator>>=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) >> __value; + } + + __simd_reference operator<<=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) << __value; + } + + __simd_reference operator&=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) & __value; + } + + __simd_reference operator|=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) | __value; + } + + __simd_reference operator^=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) ^ __value; + } }; template @@ -720,6 +939,17 @@ constexpr _Tp __variadic_sum(_Up __first, _Args... __rest) { return static_cast<_Tp>(__first) + __variadic_sum<_Tp>(__rest...); } +template +struct __nodeduce { + using type = _Tp; +}; + +template +constexpr bool __vectorizable() { + return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value && + !std::is_volatile<_Tp>::value && !std::is_same<_Tp, bool>::value; +} + _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD_ABI @@ -728,14 +958,21 @@ using scalar = __simd_abi<_StorageKind::_Scalar, 1>; template using fixed_size = __simd_abi<_StorageKind::_Array, _Np>; -#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template -_LIBCPP_INLINE_VAR constexpr int max_fixed_size = 32; -#endif +_LIBCPP_INLINE_VAR constexpr size_t max_fixed_size = 32; + template using compatible = fixed_size<16 / sizeof(_Tp)>; + +#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION +template +using native = __simd_abi<_StorageKind::_VecExt, + _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; +#else template -using native = compatible<_Tp>; +using native = + fixed_size<_Tp, _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; +#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD @@ -749,14 +986,10 @@ struct element_aligned_tag {}; struct vector_aligned_tag {}; template struct overaligned_tag {}; -#if _LIBCPP_STD_VER > 14 _LIBCPP_INLINE_VAR constexpr element_aligned_tag element_aligned{}; _LIBCPP_INLINE_VAR constexpr vector_aligned_tag vector_aligned{}; -#if !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR constexpr overaligned_tag<_Np> overaligned{}; -#endif -#endif // traits [simd.traits] template @@ -794,7 +1027,6 @@ template struct is_simd_flag_type> : std::integral_constant {}; -#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR constexpr bool is_abi_tag_v = is_abi_tag<_Tp>::value; template @@ -804,7 +1036,6 @@ _LIBCPP_INLINE_VAR constexpr bool is_simd_mask_v = is_simd_mask<_Tp>::value; template _LIBCPP_INLINE_VAR constexpr bool is_simd_flag_type_v = is_simd_flag_type<_Tp>::value; -#endif template struct abi_for_size { using type = simd_abi::fixed_size<_Np>; @@ -824,17 +1055,16 @@ struct simd_size<_Tp, __simd_abi<__kind, _Np>> "Element type should be vectorizable"); }; +// TODO: implement it. template struct memory_alignment; -#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template > _LIBCPP_INLINE_VAR constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value; template _LIBCPP_INLINE_VAR constexpr size_t memory_alignment_v = memory_alignment<_Tp, _Up>::value; -#endif // class template simd [simd.class] template @@ -972,11 +1202,6 @@ template class where_expression; // masked assignment [simd.mask.where] -template -struct __nodeduce { - using type = _Tp; -}; - template where_expression, simd<_Tp, _Abi>> where(const typename simd<_Tp, _Abi>::mask_type&, simd<_Tp, _Abi>&) noexcept; @@ -1113,7 +1338,23 @@ public: // TODO: implement simd template class simd { +public: + using value_type = _Tp; + using reference = __simd_reference<_Tp, _Tp, _Abi>; + using mask_type = simd_mask<_Tp, _Abi>; + using abi_type = _Abi; + + simd() = default; + simd(const simd&) = default; + simd& operator=(const simd&) = default; + + static constexpr size_t size() noexcept { + return simd_size<_Tp, _Abi>::value; + } + private: + __simd_storage<_Tp, _Abi> __s_; + template static constexpr bool __can_broadcast() { return (std::is_arithmetic<_Up>::value && @@ -1126,57 +1367,97 @@ private: std::is_unsigned<_Tp>::value); } -public: - using value_type = _Tp; - // TODO: this is strawman implementation. Turn it into a proxy type. - using reference = _Tp&; - using mask_type = simd_mask<_Tp, _Abi>; - - using abi_type = _Abi; + template + static constexpr decltype( + std::forward_as_tuple(std::declval<_Generator>()( + std::integral_constant())...), + bool()) + __can_generate(std::index_sequence<__indicies...>) { + return !__variadic_sum( + !__can_broadcast()( + std::integral_constant()))>()...); + } - static constexpr size_t size() noexcept { - return simd_size<_Tp, _Abi>::value; + template + static bool __can_generate(...) { + return false; } - simd() = default; + template + void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) { + int __not_used[]{((*this)[__indicies] = + __g(std::integral_constant()), + 0)...}; + (void)__not_used; + } +public: // implicit type conversion constructor template >::value && __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()>::type> - simd(const simd<_Up, simd_abi::fixed_size>&) {} + simd(const simd<_Up, simd_abi::fixed_size>& __v) { + for (size_t __i = 0; __i < size(); __i++) { + (*this)[__i] = static_cast<_Tp>(__v[__i]); + } + } // implicit broadcast constructor template ()>::type> - simd(_Up&&); + simd(_Up&& __rv) { + auto __v = static_cast<_Tp>(__rv); + for (size_t __i = 0; __i < size(); __i++) { + (*this)[__i] = __v; + } + } // generator constructor - // TODO: for now only check for the index 0. This is because C++11 doesn't - // have index_sequence, and it's hard to check for all indicies without using - // index_sequence. template ()( - std::integral_constant())), - int())()> - explicit simd(_Generator&&); + int = typename std::enable_if< + __can_generate<_Generator>(std::make_index_sequence()), + int>::type()> + explicit simd(_Generator&& __g) { + __generator_init(std::forward<_Generator>(__g), + std::make_index_sequence()); + } // load constructor - template - simd(const _Up*, _Flags); + template < + class _Up, class _Flags, + class = typename std::enable_if<__vectorizable<_Up>()>::type, + class = typename std::enable_if::value>::type> + simd(const _Up* __buffer, _Flags) { + // TODO: optimize for overaligned flags + for (size_t __i = 0; __i < size(); __i++) { + (*this)[__i] = static_cast<_Tp>(__buffer[__i]); + } + } // loads [simd.load] template - void copy_from(const _Up*, _Flags); + typename std::enable_if<__vectorizable<_Up>() && + is_simd_flag_type<_Flags>::value>::type + copy_from(const _Up* __buffer, _Flags) { + *this = simd(__buffer, _Flags()); + } // stores [simd.store] template - void copy_to(_Up*, _Flags) const; + typename std::enable_if<__vectorizable<_Up>() && + is_simd_flag_type<_Flags>::value>::type + copy_to(_Up* __buffer, _Flags) const { + // TODO: optimize for overaligned flags + for (size_t __i = 0; __i < size(); __i++) { + __buffer[__i] = static_cast<_Up>((*this)[__i]); + } + } // scalar access [simd.subscr] - reference operator[](size_t); - value_type operator[](size_t) const; + reference operator[](size_t __i) { return reference(&__s_, __i); } + + value_type operator[](size_t __i) const { return __s_.__get(__i); } // unary operators [simd.unary] simd& operator++(); diff --git a/test/std/experimental/simd/simd.abi/vector_extension.pass.cpp b/test/std/experimental/simd/simd.abi/vector_extension.pass.cpp new file mode 100644 index 000000000..dd8436618 --- /dev/null +++ b/test/std/experimental/simd/simd.abi/vector_extension.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// [simd.abi] + +#include +#include + +namespace ex = std::experimental::parallelism_v2; + +constexpr inline int reg_width() { +#if defined(__AVX__) + return 32; +#else + return 16; +#endif +} + +#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION + +static_assert( + sizeof(ex::simd>) == 1, + ""); +static_assert( + sizeof(ex::simd>) == 2, + ""); +static_assert( + sizeof(ex::simd>) == 4, + ""); +static_assert( + sizeof(ex::simd>) == 16, + ""); +static_assert( + sizeof(ex::simd>) == + 16, + ""); +static_assert( + sizeof(ex::simd>) == + 32, + ""); +static_assert( + std::is_same, + ex::__simd_abi>::value, + ""); +#else +static_assert( + std::is_same, + ex::__simd_abi>::value, + ""); + +#endif + +static_assert(std::is_same, + ex::__simd_abi>::value, + ""); + +int main() {} diff --git a/test/std/experimental/simd/simd.access/default.pass.cpp b/test/std/experimental/simd/simd.access/default.pass.cpp new file mode 100644 index 000000000..697035b66 --- /dev/null +++ b/test/std/experimental/simd/simd.access/default.pass.cpp @@ -0,0 +1,217 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// scalar access [simd.subscr] +// reference operator[](size_t); +// value_type operator[](size_t) const; + +#include +#include +#include + +namespace ex = std::experimental::parallelism_v2; + +template +void test_access() { + { + SimdType a(42), b(4); + static_assert(std::is_convertible::value, ""); + + assert(a[0] == 42); + assert(!a[0] == !42); + assert(~a[0] == ~42); + assert(+a[0] == +42); + assert(-a[0] == -42); + assert(a[0] + b[0] == 42 + 4); + assert(a[0] - b[0] == 42 - 4); + assert(a[0] * b[0] == 42 * 4); + assert(a[0] / b[0] == 42 / 4); + assert(a[0] % b[0] == 42 % 4); + assert(a[0] << b[0] == (42 << 4)); + assert(a[0] >> b[0] == (42 >> 4)); + assert(a[0] < b[0] == false); + assert(a[0] <= b[0] == false); + assert(a[0] > b[0] == true); + assert(a[0] >= b[0] == true); + assert(a[0] == b[0] == false); + assert(a[0] != b[0] == true); + assert((a[0] & b[0]) == (42 & 4)); + assert((a[0] | b[0]) == (42 | 4)); + assert((a[0] ^ b[0]) == (42 ^ 4)); + assert((a[0] && b[0]) == true); + assert((a[0] || b[0]) == true); + + { + auto c = a; + ++c[0]; + assert(c[0] == 42 + 1); + assert(c[1] == 42); + } + { + auto c = a; + auto ret = c[0]++; + assert(ret == 42); + assert(c[0] == 42 + 1); + assert(c[1] == 42); + } + { + auto c = a; + --c[0]; + assert(c[0] == 42 - 1); + assert(c[1] == 42); + } + { + auto c = a; + auto ret = c[0]--; + assert(ret == 42); + assert(c[0] == 42 - 1); + assert(c[1] == 42); + } + + { + auto c = a; + c[0] += b[0]; + assert(c[0] == 42 + 4); + assert(c[1] == 42); + } + { + auto c = a; + c[0] -= b[0]; + assert(c[0] == 42 - 4); + assert(c[1] == 42); + } + { + auto c = a; + c[0] *= b[0]; + assert(c[0] == 42 * 4); + assert(c[1] == 42); + } + { + auto c = a; + c[0] /= b[0]; + assert(c[0] == 42 / 4); + assert(c[1] == 42); + } + { + auto c = a; + c[0] %= b[0]; + assert(c[0] == 42 % 4); + assert(c[1] == 42); + } + { + auto c = a; + c[0] >>= b[0]; + assert(c[0] == (42 >> 4)); + assert(c[1] == 42); + } + { + auto c = a; + c[0] <<= b[0]; + assert(c[0] == (42 << 4)); + assert(c[1] == 42); + } + { + auto c = a; + c[0] &= b[0]; + assert(c[0] == (42 & 4)); + assert(c[1] == 42); + } + { + auto c = a; + c[0] |= b[0]; + assert(c[0] == (42 | 4)); + assert(c[1] == 42); + } + { + auto c = a; + c[0] ^= b[0]; + assert(c[0] == (42 ^ 4)); + assert(c[1] == 42); + } + + { + auto c = a; + (void)(a[0] + (c[0] += a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] -= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] *= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] /= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] %= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] >>= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] <<= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] &= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] |= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] ^= a[0])); + } + } + { + const SimdType a(42); + const SimdType b(4); + static_assert(std::is_same::value, ""); + + assert(a[0] == 42); + assert(!a[0] == !42); + assert(~a[0] == ~42); + assert(+a[0] == +42); + assert(-a[0] == -42); + assert(a[0] + b[0] == 42 + 4); + assert(a[0] - b[0] == 42 - 4); + assert(a[0] * b[0] == 42 * 4); + assert(a[0] / b[0] == 42 / 4); + assert(a[0] % b[0] == 42 % 4); + assert(a[0] << b[0] == (42 << 4)); + assert(a[0] >> b[0] == (42 >> 4)); + assert(a[0] < b[0] == false); + assert(a[0] <= b[0] == false); + assert(a[0] > b[0] == true); + assert(a[0] >= b[0] == true); + assert(a[0] == b[0] == false); + assert(a[0] != b[0] == true); + assert((a[0] & b[0]) == (42 & 4)); + assert((a[0] | b[0]) == (42 | 4)); + assert((a[0] ^ b[0]) == (42 ^ 4)); + assert((a[0] && b[0]) == true); + assert((a[0] || b[0]) == true); + } +} + +int main() { + test_access>(); + test_access>(); +} diff --git a/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp b/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp index af6b13fe8..d15f138d5 100644 --- a/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp +++ b/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp @@ -7,34 +7,40 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.casts] -// template see below simd_cast(const simd&); +// template see below ex::simd_cast<(const +// ex::simd&); + #include #include -using namespace std::experimental::parallelism_v2; - -static_assert(std::is_same(native_simd())), - native_simd>::value, - ""); +namespace ex = std::experimental::parallelism_v2; static_assert( - std::is_same(fixed_size_simd())), - fixed_size_simd>::value, + std::is_same(ex::native_simd())), + ex::native_simd>::value, ""); -static_assert(std::is_same>( - simd())), - fixed_size_simd>::value, +static_assert(std::is_same( + ex::fixed_size_simd())), + ex::fixed_size_simd>::value, ""); -static_assert(std::is_same>( - fixed_size_simd())), - simd>::value, - ""); +static_assert( + std::is_same>( + ex::simd())), + ex::fixed_size_simd>::value, + ""); + +static_assert( + std::is_same< + decltype(ex::simd_cast>( + ex::fixed_size_simd())), + ex::simd>::value, + ""); int main() {} diff --git a/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp b/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp index eb1fa55e0..b73466477 100644 --- a/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp +++ b/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp @@ -7,32 +7,35 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.casts] -// template see below static_simd_cast(const simd&); +// template see below ex::static_simd_cast<(const +// ex::simd&); #include #include -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; static_assert( - std::is_same(native_simd())), - native_simd>::value, + std::is_same(ex::native_simd())), + ex::native_simd>::value, ""); -static_assert(std::is_same>( - simd())), - fixed_size_simd>::value, - ""); +static_assert( + std::is_same>( + ex::simd())), + ex::fixed_size_simd>::value, + ""); static_assert( - std::is_same>( - fixed_size_simd())), - simd>::value, + std::is_same< + decltype(ex::static_simd_cast>( + ex::fixed_size_simd())), + ex::simd>::value, ""); int main() {} diff --git a/test/std/experimental/simd/simd.cons/broadcast.pass.cpp b/test/std/experimental/simd/simd.cons/broadcast.pass.cpp index 60230cc63..49b2b5572 100644 --- a/test/std/experimental/simd/simd.cons/broadcast.pass.cpp +++ b/test/std/experimental/simd/simd.cons/broadcast.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // See GCC PR63723. // UNSUPPORTED: gcc-4.9 @@ -20,18 +20,19 @@ #include #include -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; template auto not_supported_native_simd_ctor(Args&&... args) - -> decltype(native_simd(std::forward(args)...), void()) = delete; + -> decltype(ex::native_simd(std::forward(args)...), + void()) = delete; template void not_supported_native_simd_ctor(...) {} template auto supported_native_simd_ctor(Args&&... args) - -> decltype(native_simd(std::forward(args)...), void()) {} + -> decltype(ex::native_simd(std::forward(args)...), void()) {} template void supported_native_simd_ctor(...) = delete; @@ -55,4 +56,31 @@ void compile_narrowing_conversion() { not_supported_native_simd_ctor(3.); } -int main() {} +void compile_convertible() { + struct ConvertibleToInt { + operator int64_t() const; + }; + supported_native_simd_ctor(ConvertibleToInt()); + + struct NotConvertibleToInt {}; + not_supported_native_simd_ctor(NotConvertibleToInt()); +} + +void compile_unsigned() { + not_supported_native_simd_ctor(3u); + supported_native_simd_ctor(3u); +} + +template +void test_broadcast() { + SimdType a(3); + for (size_t i = 0; i < a.size(); i++) { + assert(a[i] == 3); + } +} + +int main() { + test_broadcast>(); + test_broadcast>(); + test_broadcast>(); +} diff --git a/test/std/experimental/simd/simd.cons/default.pass.cpp b/test/std/experimental/simd/simd.cons/default.pass.cpp new file mode 100644 index 000000000..0f12eced0 --- /dev/null +++ b/test/std/experimental/simd/simd.cons/default.pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// [simd.class] +// simd() = default; + +#include +#include + +namespace ex = std::experimental::parallelism_v2; + +int main() { + static_assert(ex::native_simd().size() > 0, ""); + static_assert(ex::fixed_size_simd().size() == 4, ""); + static_assert(ex::fixed_size_simd().size() == 5, ""); + static_assert(ex::fixed_size_simd().size() == 1, ""); + static_assert(ex::fixed_size_simd().size() == 32, ""); +} diff --git a/test/std/experimental/simd/simd.cons/generator.pass.cpp b/test/std/experimental/simd/simd.cons/generator.pass.cpp index baf7d936c..43273e896 100644 --- a/test/std/experimental/simd/simd.cons/generator.pass.cpp +++ b/test/std/experimental/simd/simd.cons/generator.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // See GCC PR63723. // UNSUPPORTED: gcc-4.9 @@ -17,30 +17,75 @@ // [simd.class] // template explicit simd(G&& gen); -#include #include +#include -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; template -auto not_supported_native_simd_ctor(Args&&... args) - -> decltype(native_simd(std::forward(args)...), void()) = delete; +auto not_supported_simd128_ctor(Args&&... args) -> decltype( + ex::fixed_size_simd(std::forward(args)...), + void()) = delete; template -void not_supported_native_simd_ctor(...) {} +void not_supported_simd128_ctor(...) {} template -auto supported_native_simd_ctor(Args&&... args) - -> decltype(native_simd(std::forward(args)...), void()) {} +auto supported_simd128_ctor(Args&&... args) -> decltype( + ex::fixed_size_simd(std::forward(args)...), + void()) {} template -void supported_native_simd_ctor(...) = delete; +void supported_simd128_ctor(...) = delete; + +struct identity { + template + int operator()(std::integral_constant) const { + return value; + } +}; void compile_generator() { - supported_native_simd_ctor([](int i) { return i; }); - not_supported_native_simd_ctor([](int i) { return float(i); }); - not_supported_native_simd_ctor([](intptr_t i) { return (int*)(i); }); - not_supported_native_simd_ctor([](int* i) { return i; }); + supported_simd128_ctor(identity()); + not_supported_simd128_ctor([](int i) { return float(i); }); + not_supported_simd128_ctor([](intptr_t i) { return (int*)(i); }); + not_supported_simd128_ctor([](int* i) { return i; }); } -int main() {} +struct limited_identity { + template + typename std::conditional::type + operator()(std::integral_constant) const { + return value; + } +}; + +void compile_limited_identity() { + supported_simd128_ctor(limited_identity()); + not_supported_simd128_ctor(limited_identity()); +} + +template +void test_generator() { + { + SimdType a([](int i) { return i; }); + assert(a[0] == 0); + assert(a[1] == 1); + assert(a[2] == 2); + assert(a[3] == 3); + } + { + SimdType a([](int i) { return 2 * i - 1; }); + assert(a[0] == -1); + assert(a[1] == 1); + assert(a[2] == 3); + assert(a[3] == 5); + } +} + +int main() { + // TODO: adjust the tests when this assertion fails. + assert(ex::native_simd::size() >= 4); + test_generator>(); + test_generator>(); +} diff --git a/test/std/experimental/simd/simd.cons/load.pass.cpp b/test/std/experimental/simd/simd.cons/load.pass.cpp new file mode 100644 index 000000000..8c87fe7a5 --- /dev/null +++ b/test/std/experimental/simd/simd.cons/load.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// [simd.class] +// template simd(const U* mem, Flags f); + +#include +#include + +#include "test_macros.h" + +namespace ex = std::experimental::parallelism_v2; + +template +auto not_supported_native_simd_ctor(Args&&... args) + -> decltype(ex::native_simd(std::forward(args)...), + void()) = delete; + +template +void not_supported_native_simd_ctor(...) {} + +template +auto supported_native_simd_ctor(Args&&... args) + -> decltype(ex::native_simd(std::forward(args)...), void()) {} + +template +void supported_native_simd_ctor(...) = delete; + +void compile_load_ctor() { + supported_native_simd_ctor((int*)nullptr, ex::element_aligned_tag()); + supported_native_simd_ctor((int*)nullptr, + ex::element_aligned_tag()); + supported_native_simd_ctor((float*)nullptr, + ex::element_aligned_tag()); + supported_native_simd_ctor((unsigned int*)nullptr, + ex::element_aligned_tag()); + supported_native_simd_ctor((float*)nullptr, + ex::element_aligned_tag()); + + not_supported_native_simd_ctor((int*)nullptr, int()); +} + +template +void test_load_ctor() { + alignas(32) int32_t buffer[] = {4, 3, 2, 1}; + { + SimdType a(buffer, ex::element_aligned_tag()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a(buffer, ex::vector_aligned_tag()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a(buffer, ex::overaligned_tag<32>()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + + { + SimdType a(buffer, ex::element_aligned); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a(buffer, ex::vector_aligned); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a(buffer, ex::overaligned<32>); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } +} + +template +void test_converting_load_ctor() { + float buffer[] = {1., 2., 4., 8.}; + SimdType a(buffer, ex::element_aligned_tag()); + assert(a[0] == 1); + assert(a[1] == 2); + assert(a[2] == 4); + assert(a[3] == 8); +} + +int main() { + // TODO: adjust the tests when this assertion fails. + assert(ex::native_simd::size() >= 4); + test_load_ctor>(); + test_load_ctor>(); + test_converting_load_ctor>(); + test_converting_load_ctor>(); +} diff --git a/test/std/experimental/simd/simd.mem/load.pass.cpp b/test/std/experimental/simd/simd.mem/load.pass.cpp new file mode 100644 index 000000000..b1a3a2b1d --- /dev/null +++ b/test/std/experimental/simd/simd.mem/load.pass.cpp @@ -0,0 +1,122 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// loads [simd.load] +// template void copy_from(const U* mem, Flags f); + +#include +#include + +#include "test_macros.h" + +namespace ex = std::experimental::parallelism_v2; + +template +auto not_supported_load(Args&&... args) -> decltype( + std::declval>().copy_from(std::forward(args)...), + void()) = delete; + +template +void not_supported_load(...) {} + +template +auto supported_load(Args&&... args) -> decltype( + std::declval>().copy_from(std::forward(args)...), + void()) {} + +template +void supported_load(...) = delete; + +void compile_load() { + supported_load((int*)nullptr, ex::element_aligned_tag()); + supported_load((int*)nullptr, ex::element_aligned_tag()); + supported_load((float*)nullptr, ex::element_aligned_tag()); + supported_load((unsigned int*)nullptr, ex::element_aligned_tag()); + supported_load((float*)nullptr, ex::element_aligned_tag()); + + not_supported_load((int*)nullptr, int()); +} + +template +void test_load() { + alignas(32) int32_t buffer[] = {4, 3, 2, 1}; + { + SimdType a; + a.copy_from(buffer, ex::element_aligned_tag()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a; + a.copy_from(buffer, ex::vector_aligned_tag()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a; + a.copy_from(buffer, ex::overaligned_tag<32>()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + + { + SimdType a; + a.copy_from(buffer, ex::element_aligned); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a; + a.copy_from(buffer, ex::vector_aligned); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a; + a.copy_from(buffer, ex::overaligned<32>); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } +} + +template +void test_converting_load() { + float buffer[] = {1., 2., 4., 8.}; + SimdType a; + a.copy_from(buffer, ex::element_aligned_tag()); + assert(a[0] == 1); + assert(a[1] == 2); + assert(a[2] == 4); + assert(a[3] == 8); +} + +int main() { + // TODO: adjust the tests when this assertion fails. + assert(ex::native_simd::size() >= 4); + test_load>(); + test_load>(); + test_converting_load>(); + test_converting_load>(); +} diff --git a/test/std/experimental/simd/simd.mem/store.pass.cpp b/test/std/experimental/simd/simd.mem/store.pass.cpp new file mode 100644 index 000000000..2025a79f2 --- /dev/null +++ b/test/std/experimental/simd/simd.mem/store.pass.cpp @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// // stores [simd.store] +// template void copy_to(U* mem, Flags f) const; + +#include +#include + +#include "test_macros.h" + +namespace ex = std::experimental::parallelism_v2; + +template +void test_store() { + SimdType a([](int i) { return 4 - i; }); + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::element_aligned_tag()); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::vector_aligned_tag()); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::overaligned_tag<32>()); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } + + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::element_aligned); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::vector_aligned); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::overaligned<32>); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } +} + +template +void test_converting_store() { + float buffer[4] = {0.}; + SimdType a([](int i) { return 1 << i; }); + a.copy_to(buffer, ex::element_aligned_tag()); + assert(buffer[0] == 1.); + assert(buffer[1] == 2.); + assert(buffer[2] == 4.); + assert(buffer[3] == 8.); +} + +int main() { + // TODO: adjust the tests when this assertion fails. + test_store>(); + test_store>(); + test_converting_store>(); + test_converting_store>(); +} diff --git a/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp b/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp index 6e244220d..b3cd92add 100644 --- a/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp +++ b/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp @@ -7,24 +7,26 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.traits] -// template struct abi_for_size { using type = see below ; }; -// template using abi_for_size_t = typename abi_for_size::type; +// template struct abi_for_size { using type = see below ; +// }; template using ex::abi_for_size_t = typename +// ex::abi_for_size::type; #include #include -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; -static_assert(std::is_same::type, - simd_abi::fixed_size<4>>::value, +static_assert(std::is_same::type, + ex::simd_abi::fixed_size<4>>::value, ""); -static_assert( - std::is_same, simd_abi::fixed_size<4>>::value, ""); +static_assert(std::is_same, + ex::simd_abi::fixed_size<4>>::value, + ""); int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp b/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp index 4f4f738a8..e87eafbdb 100644 --- a/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp @@ -7,109 +7,107 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.traits] // template struct is_abi_tag; -// template inline constexpr bool is_abi_tag_v = is_abi_tag::value; +// template inline constexpr bool ex::is_abi_tag_v = +// ex::is_abi_tag::value; #include #include #include "test_macros.h" -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; struct UserType {}; -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); - -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); - -static_assert( is_abi_tag::value, ""); -static_assert(!std::is_same>::value, - ""); - -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); - -static_assert(!is_abi_tag::value, ""); -static_assert(!is_abi_tag::value, ""); -static_assert(!is_abi_tag::value, ""); -static_assert(!is_abi_tag::value, ""); -static_assert(!is_abi_tag>::value, ""); -static_assert(!is_abi_tag>::value, ""); -static_assert(!is_abi_tag>::value, ""); -static_assert(!is_abi_tag>::value, ""); - -#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ - !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) - -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); - -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); - -static_assert( is_abi_tag_v, ""); -static_assert(!std::is_same>::value, - ""); - -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); - -static_assert(!is_abi_tag_v, ""); -static_assert(!is_abi_tag_v, ""); -static_assert(!is_abi_tag_v, ""); -static_assert(!is_abi_tag_v, ""); -static_assert(!is_abi_tag_v>, ""); -static_assert(!is_abi_tag_v>, ""); -static_assert(!is_abi_tag_v>, ""); -static_assert(!is_abi_tag_v>, ""); - -#endif +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); + +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); + +static_assert(ex::is_abi_tag::value, ""); +static_assert( + !std::is_same>::value, + ""); + +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); + +static_assert(!ex::is_abi_tag::value, ""); +static_assert(!ex::is_abi_tag::value, ""); +static_assert(!ex::is_abi_tag::value, ""); +static_assert(!ex::is_abi_tag::value, ""); +static_assert(!ex::is_abi_tag>::value, ""); +static_assert(!ex::is_abi_tag>::value, ""); +static_assert(!ex::is_abi_tag>::value, ""); +static_assert(!ex::is_abi_tag>::value, ""); + +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); + +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); + +static_assert(ex::is_abi_tag_v, ""); +static_assert( + !std::is_same>::value, + ""); + +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); + +static_assert(!ex::is_abi_tag_v, ""); +static_assert(!ex::is_abi_tag_v, ""); +static_assert(!ex::is_abi_tag_v, ""); +static_assert(!ex::is_abi_tag_v, ""); +static_assert(!ex::is_abi_tag_v>, ""); +static_assert(!ex::is_abi_tag_v>, ""); +static_assert(!ex::is_abi_tag_v>, ""); +static_assert(!ex::is_abi_tag_v>, ""); int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_simd.pass.cpp b/test/std/experimental/simd/simd.traits/is_simd.pass.cpp index 77f5d10ed..8d7c0946c 100644 --- a/test/std/experimental/simd/simd.traits/is_simd.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_simd.pass.cpp @@ -7,127 +7,123 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.traits] -// template struct is_simd; -// template inline constexpr bool is_simd_v = is_simd::value; +// template struct ex::is_simd; +// template inline constexpr bool ex::is_simd_v = +// ex::is_simd::value; #include #include #include "test_macros.h" -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; struct UserType {}; -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); - -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); - -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); - -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); - -static_assert(!is_simd::value, ""); -static_assert(!is_simd::value, ""); -static_assert(!is_simd::value, ""); -static_assert(!is_simd>::value, ""); -static_assert(!is_simd>::value, ""); -static_assert(!is_simd::value, ""); - -#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ - !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) - -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); - -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); - -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); - -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); - -static_assert(!is_simd_v, ""); -static_assert(!is_simd_v, ""); -static_assert(!is_simd_v, ""); -static_assert(!is_simd_v>, ""); -static_assert(!is_simd_v>, ""); -static_assert(!is_simd_v, ""); - -#endif +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); + +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); + +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); + +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); + +static_assert(!ex::is_simd::value, ""); +static_assert(!ex::is_simd::value, ""); +static_assert(!ex::is_simd::value, ""); +static_assert(!ex::is_simd>::value, ""); +static_assert(!ex::is_simd>::value, ""); +static_assert(!ex::is_simd::value, ""); + +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); + +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); + +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); + +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); + +static_assert(!ex::is_simd_v, ""); +static_assert(!ex::is_simd_v, ""); +static_assert(!ex::is_simd_v, ""); +static_assert(!ex::is_simd_v>, ""); +static_assert(!ex::is_simd_v>, ""); +static_assert(!ex::is_simd_v, ""); int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp b/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp index a6fe40905..ecb68fb62 100644 --- a/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp @@ -7,49 +7,45 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.traits] // template struct is_simd_flag_type; -// template inline constexpr bool is_simd_flag_type_v = is_simd_flag_type::value; +// template inline constexpr bool ex::is_simd_flag_type_v = +// ex::is_simd_flag_type::value; #include #include #include "test_macros.h" -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; struct UserType {}; -static_assert( is_simd_flag_type::value, ""); -static_assert( is_simd_flag_type::value, ""); -static_assert( is_simd_flag_type>::value, ""); -static_assert( is_simd_flag_type>::value, ""); - -static_assert(!is_simd_flag_type::value, ""); -static_assert(!is_simd_flag_type::value, ""); -static_assert(!is_simd_flag_type::value, ""); -static_assert(!is_simd_flag_type::value, ""); -static_assert(!is_simd_flag_type>::value, ""); -static_assert(!is_simd_flag_type>::value, ""); - -#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ - !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) - -static_assert( is_simd_flag_type_v, ""); -static_assert( is_simd_flag_type_v, ""); -static_assert( is_simd_flag_type_v>, ""); -static_assert( is_simd_flag_type_v>, ""); - -static_assert(!is_simd_flag_type_v, ""); -static_assert(!is_simd_flag_type_v, ""); -static_assert(!is_simd_flag_type_v, ""); -static_assert(!is_simd_flag_type_v, ""); -static_assert(!is_simd_flag_type_v>, ""); -static_assert(!is_simd_flag_type_v>, ""); - -#endif +static_assert(ex::is_simd_flag_type::value, ""); +static_assert(ex::is_simd_flag_type::value, ""); +static_assert(ex::is_simd_flag_type>::value, ""); +static_assert(ex::is_simd_flag_type>::value, ""); + +static_assert(!ex::is_simd_flag_type::value, ""); +static_assert(!ex::is_simd_flag_type::value, ""); +static_assert(!ex::is_simd_flag_type::value, ""); +static_assert(!ex::is_simd_flag_type::value, ""); +static_assert(!ex::is_simd_flag_type>::value, ""); +static_assert(!ex::is_simd_flag_type>::value, ""); + +static_assert(ex::is_simd_flag_type_v, ""); +static_assert(ex::is_simd_flag_type_v, ""); +static_assert(ex::is_simd_flag_type_v>, ""); +static_assert(ex::is_simd_flag_type_v>, ""); + +static_assert(!ex::is_simd_flag_type_v, ""); +static_assert(!ex::is_simd_flag_type_v, ""); +static_assert(!ex::is_simd_flag_type_v, ""); +static_assert(!ex::is_simd_flag_type_v, ""); +static_assert(!ex::is_simd_flag_type_v>, ""); +static_assert(!ex::is_simd_flag_type_v>, ""); int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp b/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp index 8c2e0ed5b..736802443 100644 --- a/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp @@ -7,127 +7,146 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.traits] -// template struct is_simd_mask; -// template inline constexpr bool is_simd_mask_v = is_simd_mask::value; +// template struct ex::is_simd_mask; +// template inline constexpr bool ex::is_simd_mask_v = +// ex::is_simd_mask::value; #include #include #include "test_macros.h" -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; struct UserType {}; -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); - -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); - -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); - -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); - -static_assert(!is_simd_mask::value, ""); -static_assert(!is_simd_mask::value, ""); -static_assert(!is_simd_mask::value, ""); -static_assert(!is_simd_mask>::value, ""); -static_assert(!is_simd_mask>::value, ""); -static_assert(!is_simd_mask::value, ""); - -#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ - !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) - -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); - -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); - -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); - -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); - -static_assert(!is_simd_mask_v, ""); -static_assert(!is_simd_mask_v, ""); -static_assert(!is_simd_mask_v, ""); -static_assert(!is_simd_mask_v>, ""); -static_assert(!is_simd_mask_v>, ""); -static_assert(!is_simd_mask_v, ""); - -#endif +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); + +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); + +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); + +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, + ""); + +static_assert(!ex::is_simd_mask::value, ""); +static_assert(!ex::is_simd_mask::value, ""); +static_assert(!ex::is_simd_mask::value, ""); +static_assert(!ex::is_simd_mask>::value, ""); +static_assert(!ex::is_simd_mask>::value, ""); +static_assert(!ex::is_simd_mask::value, ""); + +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); + +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); + +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); + +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); + +static_assert(!ex::is_simd_mask_v, ""); +static_assert(!ex::is_simd_mask_v, ""); +static_assert(!ex::is_simd_mask_v, ""); +static_assert(!ex::is_simd_mask_v>, ""); +static_assert(!ex::is_simd_mask_v>, ""); +static_assert(!ex::is_simd_mask_v, ""); int main() {} -- GitLab From b6244cf5afa18bd91aa3ce8117d2321c196eaa91 Mon Sep 17 00:00:00 2001 From: Tim Shen Date: Mon, 30 Jul 2018 22:21:22 +0000 Subject: [PATCH 109/495] Revert "[libcxx] implement ABI for Clang/GCC vector extension, constructors, copy_from and copy_to." This reverts commit r338309. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338316 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__config | 4 - include/experimental/__config | 7 - include/experimental/simd | 377 +++--------------- .../simd/simd.abi/vector_extension.pass.cpp | 67 ---- .../simd/simd.access/default.pass.cpp | 217 ---------- .../simd/simd.casts/simd_cast.pass.cpp | 38 +- .../simd/simd.casts/static_simd_cast.pass.cpp | 27 +- .../simd/simd.cons/broadcast.pass.cpp | 38 +- .../simd/simd.cons/default.pass.cpp | 28 -- .../simd/simd.cons/generator.pass.cpp | 73 +--- .../experimental/simd/simd.cons/load.pass.cpp | 118 ------ .../experimental/simd/simd.mem/load.pass.cpp | 122 ------ .../experimental/simd/simd.mem/store.pass.cpp | 95 ----- .../simd/simd.traits/abi_for_size.pass.cpp | 18 +- .../simd/simd.traits/is_abi_tag.pass.cpp | 180 ++++----- .../simd/simd.traits/is_simd.pass.cpp | 216 +++++----- .../simd.traits/is_simd_flag_type.pass.cpp | 58 +-- .../simd/simd.traits/is_simd_mask.pass.cpp | 239 +++++------ 18 files changed, 445 insertions(+), 1477 deletions(-) delete mode 100644 test/std/experimental/simd/simd.abi/vector_extension.pass.cpp delete mode 100644 test/std/experimental/simd/simd.access/default.pass.cpp delete mode 100644 test/std/experimental/simd/simd.cons/default.pass.cpp delete mode 100644 test/std/experimental/simd/simd.cons/load.pass.cpp delete mode 100644 test/std/experimental/simd/simd.mem/load.pass.cpp delete mode 100644 test/std/experimental/simd/simd.mem/store.pass.cpp diff --git a/include/__config b/include/__config index bba7f53ba..c01ac12be 100644 --- a/include/__config +++ b/include/__config @@ -620,8 +620,6 @@ namespace std { #define _LIBCPP_ALWAYS_INLINE __forceinline -#define _LIBCPP_HAS_NO_VECTOR_EXTENSION - #elif defined(_LIBCPP_COMPILER_IBM) #define _ALIGNAS(x) __attribute__((__aligned__(x))) @@ -654,8 +652,6 @@ namespace std { #define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) -#define _LIBCPP_HAS_NO_VECTOR_EXTENSION - #endif // _LIBCPP_COMPILER_[CLANG|GCC|MSVC|IBM] #if _LIBCPP_STD_VER >= 17 diff --git a/include/experimental/__config b/include/experimental/__config index c6f177620..55ae31b8a 100644 --- a/include/experimental/__config +++ b/include/experimental/__config @@ -64,11 +64,4 @@ #define _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI \ } _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD -// TODO: support more targets -#if defined(__AVX__) -#define _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES 32 -#else -#define _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES 16 -#endif - #endif diff --git a/include/experimental/simd b/include/experimental/simd index 2cc0d8deb..4876ccb82 100644 --- a/include/experimental/simd +++ b/include/experimental/simd @@ -651,7 +651,6 @@ public: */ #include -#include #include #include #include @@ -665,241 +664,23 @@ _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD enum class _StorageKind { _Scalar, _Array, - _VecExt, }; template <_StorageKind __kind, int _Np> struct __simd_abi {}; template -class __simd_storage {}; +struct __simd_storage_traits {}; template -class __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> { - std::array<_Tp, __num_element> __storage_; - - template - friend struct simd; - - template - friend struct simd_mask; - -public: - _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; - void __set(size_t __index, _Tp __val) noexcept { - __storage_[__index] = __val; - } +struct __simd_storage_traits<_Tp, + __simd_abi<_StorageKind::_Array, __num_element>> { + using type = std::array<_Tp, __num_element>; }; template -class __simd_storage<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> { - _Tp __storage_; - - template - friend struct simd; - - template - friend struct simd_mask; - -public: - _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; }; - void __set(size_t __index, _Tp __val) noexcept { - (&__storage_)[__index] = __val; - } -}; - -#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION - -constexpr size_t __floor_pow_of_2(size_t __val) { - return ((__val - 1) & __val) == 0 ? __val - : __floor_pow_of_2((__val - 1) & __val); -} - -constexpr size_t __ceil_pow_of_2(size_t __val) { - return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1; -} - -template -struct __vec_ext_traits { -#if !defined(_LIBCPP_COMPILER_CLANG) - typedef _Tp type __attribute__((vector_size(__ceil_pow_of_2(__bytes)))); -#endif -}; - -#if defined(_LIBCPP_COMPILER_CLANG) -#define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \ - template <> \ - struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \ - using type = \ - _TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT))); \ - } - -#define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE) \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31); \ - _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 32); - -_LIBCPP_SPECIALIZE_VEC_EXT_32(char); -_LIBCPP_SPECIALIZE_VEC_EXT_32(char16_t); -_LIBCPP_SPECIALIZE_VEC_EXT_32(char32_t); -_LIBCPP_SPECIALIZE_VEC_EXT_32(wchar_t); -_LIBCPP_SPECIALIZE_VEC_EXT_32(signed char); -_LIBCPP_SPECIALIZE_VEC_EXT_32(signed short); -_LIBCPP_SPECIALIZE_VEC_EXT_32(signed int); -_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long); -_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long long); -_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned char); -_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned short); -_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned int); -_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long); -_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long long); -_LIBCPP_SPECIALIZE_VEC_EXT_32(float); -_LIBCPP_SPECIALIZE_VEC_EXT_32(double); -_LIBCPP_SPECIALIZE_VEC_EXT_32(long double); - -#undef _LIBCPP_SPECIALIZE_VEC_EXT_32 -#undef _LIBCPP_SPECIALIZE_VEC_EXT -#endif - -template -class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> { - using _StorageType = - typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type; - - _StorageType __storage_; - - template - friend struct simd; - - template - friend struct simd_mask; - -public: - _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; - void __set(size_t __index, _Tp __val) noexcept { - __storage_[__index] = __val; - } -}; - -#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION - -template -class __simd_reference { - static_assert(std::is_same<_Vp, _Tp>::value, ""); - - template - friend struct simd; - - template - friend struct simd_mask; - - __simd_storage<_Tp, _Abi>* __ptr_; - size_t __index_; - - __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) - : __ptr_(__ptr), __index_(__index) {} - - __simd_reference(const __simd_reference&) = default; - -public: - __simd_reference() = delete; - __simd_reference& operator=(const __simd_reference&) = delete; - - operator _Vp() const { return __ptr_->__get(__index_); } - - __simd_reference operator=(_Vp __value) && { - __ptr_->__set(__index_, __value); - return *this; - } - - __simd_reference operator++() && { - return std::move(*this) = __ptr_->__get(__index_) + 1; - } - - _Vp operator++(int) && { - auto __val = __ptr_->__get(__index_); - __ptr_->__set(__index_, __val + 1); - return __val; - } - - __simd_reference operator--() && { - return std::move(*this) = __ptr_->__get(__index_) - 1; - } - - _Vp operator--(int) && { - auto __val = __ptr_->__get(__index_); - __ptr_->__set(__index_, __val - 1); - return __val; - } - - __simd_reference operator+=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) + __value; - } - - __simd_reference operator-=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) - __value; - } - - __simd_reference operator*=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) * __value; - } - - __simd_reference operator/=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) / __value; - } - - __simd_reference operator%=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) % __value; - } - - __simd_reference operator>>=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) >> __value; - } - - __simd_reference operator<<=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) << __value; - } - - __simd_reference operator&=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) & __value; - } - - __simd_reference operator|=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) | __value; - } - - __simd_reference operator^=(_Vp __value) && { - return std::move(*this) = __ptr_->__get(__index_) ^ __value; - } +struct __simd_storage_traits<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> { + using type = _Tp; }; template @@ -939,17 +720,6 @@ constexpr _Tp __variadic_sum(_Up __first, _Args... __rest) { return static_cast<_Tp>(__first) + __variadic_sum<_Tp>(__rest...); } -template -struct __nodeduce { - using type = _Tp; -}; - -template -constexpr bool __vectorizable() { - return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value && - !std::is_volatile<_Tp>::value && !std::is_same<_Tp, bool>::value; -} - _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD_ABI @@ -958,21 +728,14 @@ using scalar = __simd_abi<_StorageKind::_Scalar, 1>; template using fixed_size = __simd_abi<_StorageKind::_Array, _Np>; +#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template -_LIBCPP_INLINE_VAR constexpr size_t max_fixed_size = 32; - +_LIBCPP_INLINE_VAR constexpr int max_fixed_size = 32; +#endif template using compatible = fixed_size<16 / sizeof(_Tp)>; - -#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION -template -using native = __simd_abi<_StorageKind::_VecExt, - _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; -#else template -using native = - fixed_size<_Tp, _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; -#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION +using native = compatible<_Tp>; _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD @@ -986,10 +749,14 @@ struct element_aligned_tag {}; struct vector_aligned_tag {}; template struct overaligned_tag {}; +#if _LIBCPP_STD_VER > 14 _LIBCPP_INLINE_VAR constexpr element_aligned_tag element_aligned{}; _LIBCPP_INLINE_VAR constexpr vector_aligned_tag vector_aligned{}; +#if !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR constexpr overaligned_tag<_Np> overaligned{}; +#endif +#endif // traits [simd.traits] template @@ -1027,6 +794,7 @@ template struct is_simd_flag_type> : std::integral_constant {}; +#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR constexpr bool is_abi_tag_v = is_abi_tag<_Tp>::value; template @@ -1036,6 +804,7 @@ _LIBCPP_INLINE_VAR constexpr bool is_simd_mask_v = is_simd_mask<_Tp>::value; template _LIBCPP_INLINE_VAR constexpr bool is_simd_flag_type_v = is_simd_flag_type<_Tp>::value; +#endif template struct abi_for_size { using type = simd_abi::fixed_size<_Np>; @@ -1055,16 +824,17 @@ struct simd_size<_Tp, __simd_abi<__kind, _Np>> "Element type should be vectorizable"); }; -// TODO: implement it. template struct memory_alignment; +#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template > _LIBCPP_INLINE_VAR constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value; template _LIBCPP_INLINE_VAR constexpr size_t memory_alignment_v = memory_alignment<_Tp, _Up>::value; +#endif // class template simd [simd.class] template @@ -1202,6 +972,11 @@ template class where_expression; // masked assignment [simd.mask.where] +template +struct __nodeduce { + using type = _Tp; +}; + template where_expression, simd<_Tp, _Abi>> where(const typename simd<_Tp, _Abi>::mask_type&, simd<_Tp, _Abi>&) noexcept; @@ -1338,23 +1113,7 @@ public: // TODO: implement simd template class simd { -public: - using value_type = _Tp; - using reference = __simd_reference<_Tp, _Tp, _Abi>; - using mask_type = simd_mask<_Tp, _Abi>; - using abi_type = _Abi; - - simd() = default; - simd(const simd&) = default; - simd& operator=(const simd&) = default; - - static constexpr size_t size() noexcept { - return simd_size<_Tp, _Abi>::value; - } - private: - __simd_storage<_Tp, _Abi> __s_; - template static constexpr bool __can_broadcast() { return (std::is_arithmetic<_Up>::value && @@ -1367,97 +1126,57 @@ private: std::is_unsigned<_Tp>::value); } - template - static constexpr decltype( - std::forward_as_tuple(std::declval<_Generator>()( - std::integral_constant())...), - bool()) - __can_generate(std::index_sequence<__indicies...>) { - return !__variadic_sum( - !__can_broadcast()( - std::integral_constant()))>()...); - } +public: + using value_type = _Tp; + // TODO: this is strawman implementation. Turn it into a proxy type. + using reference = _Tp&; + using mask_type = simd_mask<_Tp, _Abi>; - template - static bool __can_generate(...) { - return false; - } + using abi_type = _Abi; - template - void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) { - int __not_used[]{((*this)[__indicies] = - __g(std::integral_constant()), - 0)...}; - (void)__not_used; + static constexpr size_t size() noexcept { + return simd_size<_Tp, _Abi>::value; } -public: + simd() = default; + // implicit type conversion constructor template >::value && __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()>::type> - simd(const simd<_Up, simd_abi::fixed_size>& __v) { - for (size_t __i = 0; __i < size(); __i++) { - (*this)[__i] = static_cast<_Tp>(__v[__i]); - } - } + simd(const simd<_Up, simd_abi::fixed_size>&) {} // implicit broadcast constructor template ()>::type> - simd(_Up&& __rv) { - auto __v = static_cast<_Tp>(__rv); - for (size_t __i = 0; __i < size(); __i++) { - (*this)[__i] = __v; - } - } + simd(_Up&&); // generator constructor + // TODO: for now only check for the index 0. This is because C++11 doesn't + // have index_sequence, and it's hard to check for all indicies without using + // index_sequence. template (std::make_index_sequence()), - int>::type()> - explicit simd(_Generator&& __g) { - __generator_init(std::forward<_Generator>(__g), - std::make_index_sequence()); - } + int = decltype(simd(std::declval<_Generator>()( + std::integral_constant())), + int())()> + explicit simd(_Generator&&); // load constructor - template < - class _Up, class _Flags, - class = typename std::enable_if<__vectorizable<_Up>()>::type, - class = typename std::enable_if::value>::type> - simd(const _Up* __buffer, _Flags) { - // TODO: optimize for overaligned flags - for (size_t __i = 0; __i < size(); __i++) { - (*this)[__i] = static_cast<_Tp>(__buffer[__i]); - } - } + template + simd(const _Up*, _Flags); // loads [simd.load] template - typename std::enable_if<__vectorizable<_Up>() && - is_simd_flag_type<_Flags>::value>::type - copy_from(const _Up* __buffer, _Flags) { - *this = simd(__buffer, _Flags()); - } + void copy_from(const _Up*, _Flags); // stores [simd.store] template - typename std::enable_if<__vectorizable<_Up>() && - is_simd_flag_type<_Flags>::value>::type - copy_to(_Up* __buffer, _Flags) const { - // TODO: optimize for overaligned flags - for (size_t __i = 0; __i < size(); __i++) { - __buffer[__i] = static_cast<_Up>((*this)[__i]); - } - } + void copy_to(_Up*, _Flags) const; // scalar access [simd.subscr] - reference operator[](size_t __i) { return reference(&__s_, __i); } - - value_type operator[](size_t __i) const { return __s_.__get(__i); } + reference operator[](size_t); + value_type operator[](size_t) const; // unary operators [simd.unary] simd& operator++(); diff --git a/test/std/experimental/simd/simd.abi/vector_extension.pass.cpp b/test/std/experimental/simd/simd.abi/vector_extension.pass.cpp deleted file mode 100644 index dd8436618..000000000 --- a/test/std/experimental/simd/simd.abi/vector_extension.pass.cpp +++ /dev/null @@ -1,67 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03, c++11, c++14 - -// -// -// [simd.abi] - -#include -#include - -namespace ex = std::experimental::parallelism_v2; - -constexpr inline int reg_width() { -#if defined(__AVX__) - return 32; -#else - return 16; -#endif -} - -#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION - -static_assert( - sizeof(ex::simd>) == 1, - ""); -static_assert( - sizeof(ex::simd>) == 2, - ""); -static_assert( - sizeof(ex::simd>) == 4, - ""); -static_assert( - sizeof(ex::simd>) == 16, - ""); -static_assert( - sizeof(ex::simd>) == - 16, - ""); -static_assert( - sizeof(ex::simd>) == - 32, - ""); -static_assert( - std::is_same, - ex::__simd_abi>::value, - ""); -#else -static_assert( - std::is_same, - ex::__simd_abi>::value, - ""); - -#endif - -static_assert(std::is_same, - ex::__simd_abi>::value, - ""); - -int main() {} diff --git a/test/std/experimental/simd/simd.access/default.pass.cpp b/test/std/experimental/simd/simd.access/default.pass.cpp deleted file mode 100644 index 697035b66..000000000 --- a/test/std/experimental/simd/simd.access/default.pass.cpp +++ /dev/null @@ -1,217 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03, c++11, c++14 - -// -// -// scalar access [simd.subscr] -// reference operator[](size_t); -// value_type operator[](size_t) const; - -#include -#include -#include - -namespace ex = std::experimental::parallelism_v2; - -template -void test_access() { - { - SimdType a(42), b(4); - static_assert(std::is_convertible::value, ""); - - assert(a[0] == 42); - assert(!a[0] == !42); - assert(~a[0] == ~42); - assert(+a[0] == +42); - assert(-a[0] == -42); - assert(a[0] + b[0] == 42 + 4); - assert(a[0] - b[0] == 42 - 4); - assert(a[0] * b[0] == 42 * 4); - assert(a[0] / b[0] == 42 / 4); - assert(a[0] % b[0] == 42 % 4); - assert(a[0] << b[0] == (42 << 4)); - assert(a[0] >> b[0] == (42 >> 4)); - assert(a[0] < b[0] == false); - assert(a[0] <= b[0] == false); - assert(a[0] > b[0] == true); - assert(a[0] >= b[0] == true); - assert(a[0] == b[0] == false); - assert(a[0] != b[0] == true); - assert((a[0] & b[0]) == (42 & 4)); - assert((a[0] | b[0]) == (42 | 4)); - assert((a[0] ^ b[0]) == (42 ^ 4)); - assert((a[0] && b[0]) == true); - assert((a[0] || b[0]) == true); - - { - auto c = a; - ++c[0]; - assert(c[0] == 42 + 1); - assert(c[1] == 42); - } - { - auto c = a; - auto ret = c[0]++; - assert(ret == 42); - assert(c[0] == 42 + 1); - assert(c[1] == 42); - } - { - auto c = a; - --c[0]; - assert(c[0] == 42 - 1); - assert(c[1] == 42); - } - { - auto c = a; - auto ret = c[0]--; - assert(ret == 42); - assert(c[0] == 42 - 1); - assert(c[1] == 42); - } - - { - auto c = a; - c[0] += b[0]; - assert(c[0] == 42 + 4); - assert(c[1] == 42); - } - { - auto c = a; - c[0] -= b[0]; - assert(c[0] == 42 - 4); - assert(c[1] == 42); - } - { - auto c = a; - c[0] *= b[0]; - assert(c[0] == 42 * 4); - assert(c[1] == 42); - } - { - auto c = a; - c[0] /= b[0]; - assert(c[0] == 42 / 4); - assert(c[1] == 42); - } - { - auto c = a; - c[0] %= b[0]; - assert(c[0] == 42 % 4); - assert(c[1] == 42); - } - { - auto c = a; - c[0] >>= b[0]; - assert(c[0] == (42 >> 4)); - assert(c[1] == 42); - } - { - auto c = a; - c[0] <<= b[0]; - assert(c[0] == (42 << 4)); - assert(c[1] == 42); - } - { - auto c = a; - c[0] &= b[0]; - assert(c[0] == (42 & 4)); - assert(c[1] == 42); - } - { - auto c = a; - c[0] |= b[0]; - assert(c[0] == (42 | 4)); - assert(c[1] == 42); - } - { - auto c = a; - c[0] ^= b[0]; - assert(c[0] == (42 ^ 4)); - assert(c[1] == 42); - } - - { - auto c = a; - (void)(a[0] + (c[0] += a[0])); - } - { - auto c = a; - (void)(a[0] + (c[0] -= a[0])); - } - { - auto c = a; - (void)(a[0] + (c[0] *= a[0])); - } - { - auto c = a; - (void)(a[0] + (c[0] /= a[0])); - } - { - auto c = a; - (void)(a[0] + (c[0] %= a[0])); - } - { - auto c = a; - (void)(a[0] + (c[0] >>= a[0])); - } - { - auto c = a; - (void)(a[0] + (c[0] <<= a[0])); - } - { - auto c = a; - (void)(a[0] + (c[0] &= a[0])); - } - { - auto c = a; - (void)(a[0] + (c[0] |= a[0])); - } - { - auto c = a; - (void)(a[0] + (c[0] ^= a[0])); - } - } - { - const SimdType a(42); - const SimdType b(4); - static_assert(std::is_same::value, ""); - - assert(a[0] == 42); - assert(!a[0] == !42); - assert(~a[0] == ~42); - assert(+a[0] == +42); - assert(-a[0] == -42); - assert(a[0] + b[0] == 42 + 4); - assert(a[0] - b[0] == 42 - 4); - assert(a[0] * b[0] == 42 * 4); - assert(a[0] / b[0] == 42 / 4); - assert(a[0] % b[0] == 42 % 4); - assert(a[0] << b[0] == (42 << 4)); - assert(a[0] >> b[0] == (42 >> 4)); - assert(a[0] < b[0] == false); - assert(a[0] <= b[0] == false); - assert(a[0] > b[0] == true); - assert(a[0] >= b[0] == true); - assert(a[0] == b[0] == false); - assert(a[0] != b[0] == true); - assert((a[0] & b[0]) == (42 & 4)); - assert((a[0] | b[0]) == (42 | 4)); - assert((a[0] ^ b[0]) == (42 ^ 4)); - assert((a[0] && b[0]) == true); - assert((a[0] || b[0]) == true); - } -} - -int main() { - test_access>(); - test_access>(); -} diff --git a/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp b/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp index d15f138d5..af6b13fe8 100644 --- a/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp +++ b/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp @@ -7,40 +7,34 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++98, c++03 // // // [simd.casts] -// template see below ex::simd_cast<(const -// ex::simd&); - +// template see below simd_cast(const simd&); #include #include -namespace ex = std::experimental::parallelism_v2; +using namespace std::experimental::parallelism_v2; -static_assert( - std::is_same(ex::native_simd())), - ex::native_simd>::value, - ""); - -static_assert(std::is_same( - ex::fixed_size_simd())), - ex::fixed_size_simd>::value, +static_assert(std::is_same(native_simd())), + native_simd>::value, ""); static_assert( - std::is_same>( - ex::simd())), - ex::fixed_size_simd>::value, + std::is_same(fixed_size_simd())), + fixed_size_simd>::value, ""); -static_assert( - std::is_same< - decltype(ex::simd_cast>( - ex::fixed_size_simd())), - ex::simd>::value, - ""); +static_assert(std::is_same>( + simd())), + fixed_size_simd>::value, + ""); + +static_assert(std::is_same>( + fixed_size_simd())), + simd>::value, + ""); int main() {} diff --git a/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp b/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp index b73466477..eb1fa55e0 100644 --- a/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp +++ b/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp @@ -7,35 +7,32 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++98, c++03 // // // [simd.casts] -// template see below ex::static_simd_cast<(const -// ex::simd&); +// template see below static_simd_cast(const simd&); #include #include -namespace ex = std::experimental::parallelism_v2; +using namespace std::experimental::parallelism_v2; static_assert( - std::is_same(ex::native_simd())), - ex::native_simd>::value, + std::is_same(native_simd())), + native_simd>::value, ""); -static_assert( - std::is_same>( - ex::simd())), - ex::fixed_size_simd>::value, - ""); +static_assert(std::is_same>( + simd())), + fixed_size_simd>::value, + ""); static_assert( - std::is_same< - decltype(ex::static_simd_cast>( - ex::fixed_size_simd())), - ex::simd>::value, + std::is_same>( + fixed_size_simd())), + simd>::value, ""); int main() {} diff --git a/test/std/experimental/simd/simd.cons/broadcast.pass.cpp b/test/std/experimental/simd/simd.cons/broadcast.pass.cpp index 49b2b5572..60230cc63 100644 --- a/test/std/experimental/simd/simd.cons/broadcast.pass.cpp +++ b/test/std/experimental/simd/simd.cons/broadcast.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++98, c++03 // See GCC PR63723. // UNSUPPORTED: gcc-4.9 @@ -20,19 +20,18 @@ #include #include -namespace ex = std::experimental::parallelism_v2; +using namespace std::experimental::parallelism_v2; template auto not_supported_native_simd_ctor(Args&&... args) - -> decltype(ex::native_simd(std::forward(args)...), - void()) = delete; + -> decltype(native_simd(std::forward(args)...), void()) = delete; template void not_supported_native_simd_ctor(...) {} template auto supported_native_simd_ctor(Args&&... args) - -> decltype(ex::native_simd(std::forward(args)...), void()) {} + -> decltype(native_simd(std::forward(args)...), void()) {} template void supported_native_simd_ctor(...) = delete; @@ -56,31 +55,4 @@ void compile_narrowing_conversion() { not_supported_native_simd_ctor(3.); } -void compile_convertible() { - struct ConvertibleToInt { - operator int64_t() const; - }; - supported_native_simd_ctor(ConvertibleToInt()); - - struct NotConvertibleToInt {}; - not_supported_native_simd_ctor(NotConvertibleToInt()); -} - -void compile_unsigned() { - not_supported_native_simd_ctor(3u); - supported_native_simd_ctor(3u); -} - -template -void test_broadcast() { - SimdType a(3); - for (size_t i = 0; i < a.size(); i++) { - assert(a[i] == 3); - } -} - -int main() { - test_broadcast>(); - test_broadcast>(); - test_broadcast>(); -} +int main() {} diff --git a/test/std/experimental/simd/simd.cons/default.pass.cpp b/test/std/experimental/simd/simd.cons/default.pass.cpp deleted file mode 100644 index 0f12eced0..000000000 --- a/test/std/experimental/simd/simd.cons/default.pass.cpp +++ /dev/null @@ -1,28 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03, c++11, c++14 - -// -// -// [simd.class] -// simd() = default; - -#include -#include - -namespace ex = std::experimental::parallelism_v2; - -int main() { - static_assert(ex::native_simd().size() > 0, ""); - static_assert(ex::fixed_size_simd().size() == 4, ""); - static_assert(ex::fixed_size_simd().size() == 5, ""); - static_assert(ex::fixed_size_simd().size() == 1, ""); - static_assert(ex::fixed_size_simd().size() == 32, ""); -} diff --git a/test/std/experimental/simd/simd.cons/generator.pass.cpp b/test/std/experimental/simd/simd.cons/generator.pass.cpp index 43273e896..baf7d936c 100644 --- a/test/std/experimental/simd/simd.cons/generator.pass.cpp +++ b/test/std/experimental/simd/simd.cons/generator.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++98, c++03 // See GCC PR63723. // UNSUPPORTED: gcc-4.9 @@ -17,75 +17,30 @@ // [simd.class] // template explicit simd(G&& gen); -#include #include +#include -namespace ex = std::experimental::parallelism_v2; +using namespace std::experimental::parallelism_v2; template -auto not_supported_simd128_ctor(Args&&... args) -> decltype( - ex::fixed_size_simd(std::forward(args)...), - void()) = delete; +auto not_supported_native_simd_ctor(Args&&... args) + -> decltype(native_simd(std::forward(args)...), void()) = delete; template -void not_supported_simd128_ctor(...) {} +void not_supported_native_simd_ctor(...) {} template -auto supported_simd128_ctor(Args&&... args) -> decltype( - ex::fixed_size_simd(std::forward(args)...), - void()) {} +auto supported_native_simd_ctor(Args&&... args) + -> decltype(native_simd(std::forward(args)...), void()) {} template -void supported_simd128_ctor(...) = delete; - -struct identity { - template - int operator()(std::integral_constant) const { - return value; - } -}; +void supported_native_simd_ctor(...) = delete; void compile_generator() { - supported_simd128_ctor(identity()); - not_supported_simd128_ctor([](int i) { return float(i); }); - not_supported_simd128_ctor([](intptr_t i) { return (int*)(i); }); - not_supported_simd128_ctor([](int* i) { return i; }); + supported_native_simd_ctor([](int i) { return i; }); + not_supported_native_simd_ctor([](int i) { return float(i); }); + not_supported_native_simd_ctor([](intptr_t i) { return (int*)(i); }); + not_supported_native_simd_ctor([](int* i) { return i; }); } -struct limited_identity { - template - typename std::conditional::type - operator()(std::integral_constant) const { - return value; - } -}; - -void compile_limited_identity() { - supported_simd128_ctor(limited_identity()); - not_supported_simd128_ctor(limited_identity()); -} - -template -void test_generator() { - { - SimdType a([](int i) { return i; }); - assert(a[0] == 0); - assert(a[1] == 1); - assert(a[2] == 2); - assert(a[3] == 3); - } - { - SimdType a([](int i) { return 2 * i - 1; }); - assert(a[0] == -1); - assert(a[1] == 1); - assert(a[2] == 3); - assert(a[3] == 5); - } -} - -int main() { - // TODO: adjust the tests when this assertion fails. - assert(ex::native_simd::size() >= 4); - test_generator>(); - test_generator>(); -} +int main() {} diff --git a/test/std/experimental/simd/simd.cons/load.pass.cpp b/test/std/experimental/simd/simd.cons/load.pass.cpp deleted file mode 100644 index 8c87fe7a5..000000000 --- a/test/std/experimental/simd/simd.cons/load.pass.cpp +++ /dev/null @@ -1,118 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03, c++11, c++14 - -// -// -// [simd.class] -// template simd(const U* mem, Flags f); - -#include -#include - -#include "test_macros.h" - -namespace ex = std::experimental::parallelism_v2; - -template -auto not_supported_native_simd_ctor(Args&&... args) - -> decltype(ex::native_simd(std::forward(args)...), - void()) = delete; - -template -void not_supported_native_simd_ctor(...) {} - -template -auto supported_native_simd_ctor(Args&&... args) - -> decltype(ex::native_simd(std::forward(args)...), void()) {} - -template -void supported_native_simd_ctor(...) = delete; - -void compile_load_ctor() { - supported_native_simd_ctor((int*)nullptr, ex::element_aligned_tag()); - supported_native_simd_ctor((int*)nullptr, - ex::element_aligned_tag()); - supported_native_simd_ctor((float*)nullptr, - ex::element_aligned_tag()); - supported_native_simd_ctor((unsigned int*)nullptr, - ex::element_aligned_tag()); - supported_native_simd_ctor((float*)nullptr, - ex::element_aligned_tag()); - - not_supported_native_simd_ctor((int*)nullptr, int()); -} - -template -void test_load_ctor() { - alignas(32) int32_t buffer[] = {4, 3, 2, 1}; - { - SimdType a(buffer, ex::element_aligned_tag()); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } - { - SimdType a(buffer, ex::vector_aligned_tag()); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } - { - SimdType a(buffer, ex::overaligned_tag<32>()); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } - - { - SimdType a(buffer, ex::element_aligned); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } - { - SimdType a(buffer, ex::vector_aligned); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } - { - SimdType a(buffer, ex::overaligned<32>); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } -} - -template -void test_converting_load_ctor() { - float buffer[] = {1., 2., 4., 8.}; - SimdType a(buffer, ex::element_aligned_tag()); - assert(a[0] == 1); - assert(a[1] == 2); - assert(a[2] == 4); - assert(a[3] == 8); -} - -int main() { - // TODO: adjust the tests when this assertion fails. - assert(ex::native_simd::size() >= 4); - test_load_ctor>(); - test_load_ctor>(); - test_converting_load_ctor>(); - test_converting_load_ctor>(); -} diff --git a/test/std/experimental/simd/simd.mem/load.pass.cpp b/test/std/experimental/simd/simd.mem/load.pass.cpp deleted file mode 100644 index b1a3a2b1d..000000000 --- a/test/std/experimental/simd/simd.mem/load.pass.cpp +++ /dev/null @@ -1,122 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03, c++11, c++14 - -// -// -// loads [simd.load] -// template void copy_from(const U* mem, Flags f); - -#include -#include - -#include "test_macros.h" - -namespace ex = std::experimental::parallelism_v2; - -template -auto not_supported_load(Args&&... args) -> decltype( - std::declval>().copy_from(std::forward(args)...), - void()) = delete; - -template -void not_supported_load(...) {} - -template -auto supported_load(Args&&... args) -> decltype( - std::declval>().copy_from(std::forward(args)...), - void()) {} - -template -void supported_load(...) = delete; - -void compile_load() { - supported_load((int*)nullptr, ex::element_aligned_tag()); - supported_load((int*)nullptr, ex::element_aligned_tag()); - supported_load((float*)nullptr, ex::element_aligned_tag()); - supported_load((unsigned int*)nullptr, ex::element_aligned_tag()); - supported_load((float*)nullptr, ex::element_aligned_tag()); - - not_supported_load((int*)nullptr, int()); -} - -template -void test_load() { - alignas(32) int32_t buffer[] = {4, 3, 2, 1}; - { - SimdType a; - a.copy_from(buffer, ex::element_aligned_tag()); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } - { - SimdType a; - a.copy_from(buffer, ex::vector_aligned_tag()); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } - { - SimdType a; - a.copy_from(buffer, ex::overaligned_tag<32>()); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } - - { - SimdType a; - a.copy_from(buffer, ex::element_aligned); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } - { - SimdType a; - a.copy_from(buffer, ex::vector_aligned); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } - { - SimdType a; - a.copy_from(buffer, ex::overaligned<32>); - assert(a[0] == 4); - assert(a[1] == 3); - assert(a[2] == 2); - assert(a[3] == 1); - } -} - -template -void test_converting_load() { - float buffer[] = {1., 2., 4., 8.}; - SimdType a; - a.copy_from(buffer, ex::element_aligned_tag()); - assert(a[0] == 1); - assert(a[1] == 2); - assert(a[2] == 4); - assert(a[3] == 8); -} - -int main() { - // TODO: adjust the tests when this assertion fails. - assert(ex::native_simd::size() >= 4); - test_load>(); - test_load>(); - test_converting_load>(); - test_converting_load>(); -} diff --git a/test/std/experimental/simd/simd.mem/store.pass.cpp b/test/std/experimental/simd/simd.mem/store.pass.cpp deleted file mode 100644 index 2025a79f2..000000000 --- a/test/std/experimental/simd/simd.mem/store.pass.cpp +++ /dev/null @@ -1,95 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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. -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++98, c++03, c++11, c++14 - -// -// -// // stores [simd.store] -// template void copy_to(U* mem, Flags f) const; - -#include -#include - -#include "test_macros.h" - -namespace ex = std::experimental::parallelism_v2; - -template -void test_store() { - SimdType a([](int i) { return 4 - i; }); - { - alignas(32) int32_t buffer[4] = {0}; - a.copy_to(buffer, ex::element_aligned_tag()); - assert(buffer[0] == 4); - assert(buffer[1] == 3); - assert(buffer[2] == 2); - assert(buffer[3] == 1); - } - { - alignas(32) int32_t buffer[4] = {0}; - a.copy_to(buffer, ex::vector_aligned_tag()); - assert(buffer[0] == 4); - assert(buffer[1] == 3); - assert(buffer[2] == 2); - assert(buffer[3] == 1); - } - { - alignas(32) int32_t buffer[4] = {0}; - a.copy_to(buffer, ex::overaligned_tag<32>()); - assert(buffer[0] == 4); - assert(buffer[1] == 3); - assert(buffer[2] == 2); - assert(buffer[3] == 1); - } - - { - alignas(32) int32_t buffer[4] = {0}; - a.copy_to(buffer, ex::element_aligned); - assert(buffer[0] == 4); - assert(buffer[1] == 3); - assert(buffer[2] == 2); - assert(buffer[3] == 1); - } - { - alignas(32) int32_t buffer[4] = {0}; - a.copy_to(buffer, ex::vector_aligned); - assert(buffer[0] == 4); - assert(buffer[1] == 3); - assert(buffer[2] == 2); - assert(buffer[3] == 1); - } - { - alignas(32) int32_t buffer[4] = {0}; - a.copy_to(buffer, ex::overaligned<32>); - assert(buffer[0] == 4); - assert(buffer[1] == 3); - assert(buffer[2] == 2); - assert(buffer[3] == 1); - } -} - -template -void test_converting_store() { - float buffer[4] = {0.}; - SimdType a([](int i) { return 1 << i; }); - a.copy_to(buffer, ex::element_aligned_tag()); - assert(buffer[0] == 1.); - assert(buffer[1] == 2.); - assert(buffer[2] == 4.); - assert(buffer[3] == 8.); -} - -int main() { - // TODO: adjust the tests when this assertion fails. - test_store>(); - test_store>(); - test_converting_store>(); - test_converting_store>(); -} diff --git a/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp b/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp index b3cd92add..6e244220d 100644 --- a/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp +++ b/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp @@ -7,26 +7,24 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++98, c++03 // // // [simd.traits] -// template struct abi_for_size { using type = see below ; -// }; template using ex::abi_for_size_t = typename -// ex::abi_for_size::type; +// template struct abi_for_size { using type = see below ; }; +// template using abi_for_size_t = typename abi_for_size::type; #include #include -namespace ex = std::experimental::parallelism_v2; +using namespace std::experimental::parallelism_v2; -static_assert(std::is_same::type, - ex::simd_abi::fixed_size<4>>::value, +static_assert(std::is_same::type, + simd_abi::fixed_size<4>>::value, ""); -static_assert(std::is_same, - ex::simd_abi::fixed_size<4>>::value, - ""); +static_assert( + std::is_same, simd_abi::fixed_size<4>>::value, ""); int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp b/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp index e87eafbdb..4f4f738a8 100644 --- a/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp @@ -7,107 +7,109 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++98, c++03 // // // [simd.traits] // template struct is_abi_tag; -// template inline constexpr bool ex::is_abi_tag_v = -// ex::is_abi_tag::value; +// template inline constexpr bool is_abi_tag_v = is_abi_tag::value; #include #include #include "test_macros.h" -namespace ex = std::experimental::parallelism_v2; +using namespace std::experimental::parallelism_v2; struct UserType {}; -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); - -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); - -static_assert(ex::is_abi_tag::value, ""); -static_assert( - !std::is_same>::value, - ""); - -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); -static_assert(ex::is_abi_tag>::value, ""); - -static_assert(!ex::is_abi_tag::value, ""); -static_assert(!ex::is_abi_tag::value, ""); -static_assert(!ex::is_abi_tag::value, ""); -static_assert(!ex::is_abi_tag::value, ""); -static_assert(!ex::is_abi_tag>::value, ""); -static_assert(!ex::is_abi_tag>::value, ""); -static_assert(!ex::is_abi_tag>::value, ""); -static_assert(!ex::is_abi_tag>::value, ""); - -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); - -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); - -static_assert(ex::is_abi_tag_v, ""); -static_assert( - !std::is_same>::value, - ""); - -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); -static_assert(ex::is_abi_tag_v>, ""); - -static_assert(!ex::is_abi_tag_v, ""); -static_assert(!ex::is_abi_tag_v, ""); -static_assert(!ex::is_abi_tag_v, ""); -static_assert(!ex::is_abi_tag_v, ""); -static_assert(!ex::is_abi_tag_v>, ""); -static_assert(!ex::is_abi_tag_v>, ""); -static_assert(!ex::is_abi_tag_v>, ""); -static_assert(!ex::is_abi_tag_v>, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); + +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); + +static_assert( is_abi_tag::value, ""); +static_assert(!std::is_same>::value, + ""); + +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); +static_assert( is_abi_tag>::value, ""); + +static_assert(!is_abi_tag::value, ""); +static_assert(!is_abi_tag::value, ""); +static_assert(!is_abi_tag::value, ""); +static_assert(!is_abi_tag::value, ""); +static_assert(!is_abi_tag>::value, ""); +static_assert(!is_abi_tag>::value, ""); +static_assert(!is_abi_tag>::value, ""); +static_assert(!is_abi_tag>::value, ""); + +#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ + !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) + +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); + +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); + +static_assert( is_abi_tag_v, ""); +static_assert(!std::is_same>::value, + ""); + +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); +static_assert( is_abi_tag_v>, ""); + +static_assert(!is_abi_tag_v, ""); +static_assert(!is_abi_tag_v, ""); +static_assert(!is_abi_tag_v, ""); +static_assert(!is_abi_tag_v, ""); +static_assert(!is_abi_tag_v>, ""); +static_assert(!is_abi_tag_v>, ""); +static_assert(!is_abi_tag_v>, ""); +static_assert(!is_abi_tag_v>, ""); + +#endif int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_simd.pass.cpp b/test/std/experimental/simd/simd.traits/is_simd.pass.cpp index 8d7c0946c..77f5d10ed 100644 --- a/test/std/experimental/simd/simd.traits/is_simd.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_simd.pass.cpp @@ -7,123 +7,127 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++98, c++03 // // // [simd.traits] -// template struct ex::is_simd; -// template inline constexpr bool ex::is_simd_v = -// ex::is_simd::value; +// template struct is_simd; +// template inline constexpr bool is_simd_v = is_simd::value; #include #include #include "test_macros.h" -namespace ex = std::experimental::parallelism_v2; +using namespace std::experimental::parallelism_v2; struct UserType {}; -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); - -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); - -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); - -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); -static_assert(ex::is_simd>::value, ""); - -static_assert(!ex::is_simd::value, ""); -static_assert(!ex::is_simd::value, ""); -static_assert(!ex::is_simd::value, ""); -static_assert(!ex::is_simd>::value, ""); -static_assert(!ex::is_simd>::value, ""); -static_assert(!ex::is_simd::value, ""); - -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); - -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); - -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); - -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); -static_assert(ex::is_simd_v>, ""); - -static_assert(!ex::is_simd_v, ""); -static_assert(!ex::is_simd_v, ""); -static_assert(!ex::is_simd_v, ""); -static_assert(!ex::is_simd_v>, ""); -static_assert(!ex::is_simd_v>, ""); -static_assert(!ex::is_simd_v, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); + +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); + +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); + +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); +static_assert( is_simd>::value, ""); + +static_assert(!is_simd::value, ""); +static_assert(!is_simd::value, ""); +static_assert(!is_simd::value, ""); +static_assert(!is_simd>::value, ""); +static_assert(!is_simd>::value, ""); +static_assert(!is_simd::value, ""); + +#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ + !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) + +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); + +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); + +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); + +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); +static_assert( is_simd_v>, ""); + +static_assert(!is_simd_v, ""); +static_assert(!is_simd_v, ""); +static_assert(!is_simd_v, ""); +static_assert(!is_simd_v>, ""); +static_assert(!is_simd_v>, ""); +static_assert(!is_simd_v, ""); + +#endif int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp b/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp index ecb68fb62..a6fe40905 100644 --- a/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp @@ -7,45 +7,49 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++98, c++03 // // // [simd.traits] // template struct is_simd_flag_type; -// template inline constexpr bool ex::is_simd_flag_type_v = -// ex::is_simd_flag_type::value; +// template inline constexpr bool is_simd_flag_type_v = is_simd_flag_type::value; #include #include #include "test_macros.h" -namespace ex = std::experimental::parallelism_v2; +using namespace std::experimental::parallelism_v2; struct UserType {}; -static_assert(ex::is_simd_flag_type::value, ""); -static_assert(ex::is_simd_flag_type::value, ""); -static_assert(ex::is_simd_flag_type>::value, ""); -static_assert(ex::is_simd_flag_type>::value, ""); - -static_assert(!ex::is_simd_flag_type::value, ""); -static_assert(!ex::is_simd_flag_type::value, ""); -static_assert(!ex::is_simd_flag_type::value, ""); -static_assert(!ex::is_simd_flag_type::value, ""); -static_assert(!ex::is_simd_flag_type>::value, ""); -static_assert(!ex::is_simd_flag_type>::value, ""); - -static_assert(ex::is_simd_flag_type_v, ""); -static_assert(ex::is_simd_flag_type_v, ""); -static_assert(ex::is_simd_flag_type_v>, ""); -static_assert(ex::is_simd_flag_type_v>, ""); - -static_assert(!ex::is_simd_flag_type_v, ""); -static_assert(!ex::is_simd_flag_type_v, ""); -static_assert(!ex::is_simd_flag_type_v, ""); -static_assert(!ex::is_simd_flag_type_v, ""); -static_assert(!ex::is_simd_flag_type_v>, ""); -static_assert(!ex::is_simd_flag_type_v>, ""); +static_assert( is_simd_flag_type::value, ""); +static_assert( is_simd_flag_type::value, ""); +static_assert( is_simd_flag_type>::value, ""); +static_assert( is_simd_flag_type>::value, ""); + +static_assert(!is_simd_flag_type::value, ""); +static_assert(!is_simd_flag_type::value, ""); +static_assert(!is_simd_flag_type::value, ""); +static_assert(!is_simd_flag_type::value, ""); +static_assert(!is_simd_flag_type>::value, ""); +static_assert(!is_simd_flag_type>::value, ""); + +#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ + !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) + +static_assert( is_simd_flag_type_v, ""); +static_assert( is_simd_flag_type_v, ""); +static_assert( is_simd_flag_type_v>, ""); +static_assert( is_simd_flag_type_v>, ""); + +static_assert(!is_simd_flag_type_v, ""); +static_assert(!is_simd_flag_type_v, ""); +static_assert(!is_simd_flag_type_v, ""); +static_assert(!is_simd_flag_type_v, ""); +static_assert(!is_simd_flag_type_v>, ""); +static_assert(!is_simd_flag_type_v>, ""); + +#endif int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp b/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp index 736802443..8c2e0ed5b 100644 --- a/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp @@ -7,146 +7,127 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03, c++11, c++14 +// UNSUPPORTED: c++98, c++03 // // // [simd.traits] -// template struct ex::is_simd_mask; -// template inline constexpr bool ex::is_simd_mask_v = -// ex::is_simd_mask::value; +// template struct is_simd_mask; +// template inline constexpr bool is_simd_mask_v = is_simd_mask::value; #include #include #include "test_macros.h" -namespace ex = std::experimental::parallelism_v2; +using namespace std::experimental::parallelism_v2; struct UserType {}; -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); - -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); - -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, ""); - -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, - ""); -static_assert(ex::is_simd_mask>::value, ""); -static_assert(ex::is_simd_mask>::value, - ""); - -static_assert(!ex::is_simd_mask::value, ""); -static_assert(!ex::is_simd_mask::value, ""); -static_assert(!ex::is_simd_mask::value, ""); -static_assert(!ex::is_simd_mask>::value, ""); -static_assert(!ex::is_simd_mask>::value, ""); -static_assert(!ex::is_simd_mask::value, ""); - -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); - -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); - -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); - -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); -static_assert(ex::is_simd_mask_v>, ""); - -static_assert(!ex::is_simd_mask_v, ""); -static_assert(!ex::is_simd_mask_v, ""); -static_assert(!ex::is_simd_mask_v, ""); -static_assert(!ex::is_simd_mask_v>, ""); -static_assert(!ex::is_simd_mask_v>, ""); -static_assert(!ex::is_simd_mask_v, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); + +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); + +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); + +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); +static_assert( is_simd_mask>::value, ""); + +static_assert(!is_simd_mask::value, ""); +static_assert(!is_simd_mask::value, ""); +static_assert(!is_simd_mask::value, ""); +static_assert(!is_simd_mask>::value, ""); +static_assert(!is_simd_mask>::value, ""); +static_assert(!is_simd_mask::value, ""); + +#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ + !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) + +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); + +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); + +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); + +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); +static_assert( is_simd_mask_v>, ""); + +static_assert(!is_simd_mask_v, ""); +static_assert(!is_simd_mask_v, ""); +static_assert(!is_simd_mask_v, ""); +static_assert(!is_simd_mask_v>, ""); +static_assert(!is_simd_mask_v>, ""); +static_assert(!is_simd_mask_v, ""); + +#endif int main() {} -- GitLab From 154f393a5cfdbc44ce8084dda521d72f07e14f73 Mon Sep 17 00:00:00 2001 From: Tim Shen Date: Mon, 30 Jul 2018 22:27:38 +0000 Subject: [PATCH 110/495] Re-apply "[libcxx] implement ABI for Clang/GCC vector extension, constructors, copy_from and copy_to." ...with proper guarding #ifdefs for unsupported C++11. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338318 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__config | 4 + include/experimental/__config | 7 + include/experimental/simd | 381 +++++++++++++++--- .../simd/simd.abi/vector_extension.pass.cpp | 67 +++ .../simd/simd.access/default.pass.cpp | 217 ++++++++++ .../simd/simd.casts/simd_cast.pass.cpp | 38 +- .../simd/simd.casts/static_simd_cast.pass.cpp | 27 +- .../simd/simd.cons/broadcast.pass.cpp | 38 +- .../simd/simd.cons/default.pass.cpp | 28 ++ .../simd/simd.cons/generator.pass.cpp | 73 +++- .../experimental/simd/simd.cons/load.pass.cpp | 118 ++++++ .../experimental/simd/simd.mem/load.pass.cpp | 122 ++++++ .../experimental/simd/simd.mem/store.pass.cpp | 95 +++++ .../simd/simd.traits/abi_for_size.pass.cpp | 18 +- .../simd/simd.traits/is_abi_tag.pass.cpp | 180 ++++----- .../simd/simd.traits/is_simd.pass.cpp | 216 +++++----- .../simd.traits/is_simd_flag_type.pass.cpp | 58 ++- .../simd/simd.traits/is_simd_mask.pass.cpp | 239 ++++++----- 18 files changed, 1481 insertions(+), 445 deletions(-) create mode 100644 test/std/experimental/simd/simd.abi/vector_extension.pass.cpp create mode 100644 test/std/experimental/simd/simd.access/default.pass.cpp create mode 100644 test/std/experimental/simd/simd.cons/default.pass.cpp create mode 100644 test/std/experimental/simd/simd.cons/load.pass.cpp create mode 100644 test/std/experimental/simd/simd.mem/load.pass.cpp create mode 100644 test/std/experimental/simd/simd.mem/store.pass.cpp diff --git a/include/__config b/include/__config index c01ac12be..bba7f53ba 100644 --- a/include/__config +++ b/include/__config @@ -620,6 +620,8 @@ namespace std { #define _LIBCPP_ALWAYS_INLINE __forceinline +#define _LIBCPP_HAS_NO_VECTOR_EXTENSION + #elif defined(_LIBCPP_COMPILER_IBM) #define _ALIGNAS(x) __attribute__((__aligned__(x))) @@ -652,6 +654,8 @@ namespace std { #define _LIBCPP_ALWAYS_INLINE __attribute__ ((__always_inline__)) +#define _LIBCPP_HAS_NO_VECTOR_EXTENSION + #endif // _LIBCPP_COMPILER_[CLANG|GCC|MSVC|IBM] #if _LIBCPP_STD_VER >= 17 diff --git a/include/experimental/__config b/include/experimental/__config index 55ae31b8a..c6f177620 100644 --- a/include/experimental/__config +++ b/include/experimental/__config @@ -64,4 +64,11 @@ #define _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI \ } _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD +// TODO: support more targets +#if defined(__AVX__) +#define _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES 32 +#else +#define _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES 16 +#endif + #endif diff --git a/include/experimental/simd b/include/experimental/simd index 4876ccb82..6580443f7 100644 --- a/include/experimental/simd +++ b/include/experimental/simd @@ -651,6 +651,7 @@ public: */ #include +#include #include #include #include @@ -661,26 +662,246 @@ public: _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD +#if _LIBCPP_STD_VER >= 17 + enum class _StorageKind { _Scalar, _Array, + _VecExt, }; template <_StorageKind __kind, int _Np> struct __simd_abi {}; template -struct __simd_storage_traits {}; +class __simd_storage {}; template -struct __simd_storage_traits<_Tp, - __simd_abi<_StorageKind::_Array, __num_element>> { - using type = std::array<_Tp, __num_element>; +class __simd_storage<_Tp, __simd_abi<_StorageKind::_Array, __num_element>> { + std::array<_Tp, __num_element> __storage_; + + template + friend struct simd; + + template + friend struct simd_mask; + +public: + _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; + void __set(size_t __index, _Tp __val) noexcept { + __storage_[__index] = __val; + } }; template -struct __simd_storage_traits<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> { - using type = _Tp; +class __simd_storage<_Tp, __simd_abi<_StorageKind::_Scalar, 1>> { + _Tp __storage_; + + template + friend struct simd; + + template + friend struct simd_mask; + +public: + _Tp __get(size_t __index) const noexcept { return (&__storage_)[__index]; }; + void __set(size_t __index, _Tp __val) noexcept { + (&__storage_)[__index] = __val; + } +}; + +#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION + +constexpr size_t __floor_pow_of_2(size_t __val) { + return ((__val - 1) & __val) == 0 ? __val + : __floor_pow_of_2((__val - 1) & __val); +} + +constexpr size_t __ceil_pow_of_2(size_t __val) { + return __val == 1 ? 1 : __floor_pow_of_2(__val - 1) << 1; +} + +template +struct __vec_ext_traits { +#if !defined(_LIBCPP_COMPILER_CLANG) + typedef _Tp type __attribute__((vector_size(__ceil_pow_of_2(__bytes)))); +#endif +}; + +#if defined(_LIBCPP_COMPILER_CLANG) +#define _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, _NUM_ELEMENT) \ + template <> \ + struct __vec_ext_traits<_TYPE, sizeof(_TYPE) * _NUM_ELEMENT> { \ + using type = \ + _TYPE __attribute__((vector_size(sizeof(_TYPE) * _NUM_ELEMENT))); \ + } + +#define _LIBCPP_SPECIALIZE_VEC_EXT_32(_TYPE) \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 1); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 2); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 3); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 4); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 5); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 6); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 7); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 8); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 9); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 10); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 11); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 12); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 13); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 14); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 15); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 16); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 17); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 18); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 19); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 20); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 21); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 22); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 23); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 24); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 25); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 26); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 27); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 28); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 29); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 30); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 31); \ + _LIBCPP_SPECIALIZE_VEC_EXT(_TYPE, 32); + +_LIBCPP_SPECIALIZE_VEC_EXT_32(char); +_LIBCPP_SPECIALIZE_VEC_EXT_32(char16_t); +_LIBCPP_SPECIALIZE_VEC_EXT_32(char32_t); +_LIBCPP_SPECIALIZE_VEC_EXT_32(wchar_t); +_LIBCPP_SPECIALIZE_VEC_EXT_32(signed char); +_LIBCPP_SPECIALIZE_VEC_EXT_32(signed short); +_LIBCPP_SPECIALIZE_VEC_EXT_32(signed int); +_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long); +_LIBCPP_SPECIALIZE_VEC_EXT_32(signed long long); +_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned char); +_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned short); +_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned int); +_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long); +_LIBCPP_SPECIALIZE_VEC_EXT_32(unsigned long long); +_LIBCPP_SPECIALIZE_VEC_EXT_32(float); +_LIBCPP_SPECIALIZE_VEC_EXT_32(double); +_LIBCPP_SPECIALIZE_VEC_EXT_32(long double); + +#undef _LIBCPP_SPECIALIZE_VEC_EXT_32 +#undef _LIBCPP_SPECIALIZE_VEC_EXT +#endif + +template +class __simd_storage<_Tp, __simd_abi<_StorageKind::_VecExt, __num_element>> { + using _StorageType = + typename __vec_ext_traits<_Tp, sizeof(_Tp) * __num_element>::type; + + _StorageType __storage_; + + template + friend struct simd; + + template + friend struct simd_mask; + +public: + _Tp __get(size_t __index) const noexcept { return __storage_[__index]; }; + void __set(size_t __index, _Tp __val) noexcept { + __storage_[__index] = __val; + } +}; + +#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION + +template +class __simd_reference { + static_assert(std::is_same<_Vp, _Tp>::value, ""); + + template + friend struct simd; + + template + friend struct simd_mask; + + __simd_storage<_Tp, _Abi>* __ptr_; + size_t __index_; + + __simd_reference(__simd_storage<_Tp, _Abi>* __ptr, size_t __index) + : __ptr_(__ptr), __index_(__index) {} + + __simd_reference(const __simd_reference&) = default; + +public: + __simd_reference() = delete; + __simd_reference& operator=(const __simd_reference&) = delete; + + operator _Vp() const { return __ptr_->__get(__index_); } + + __simd_reference operator=(_Vp __value) && { + __ptr_->__set(__index_, __value); + return *this; + } + + __simd_reference operator++() && { + return std::move(*this) = __ptr_->__get(__index_) + 1; + } + + _Vp operator++(int) && { + auto __val = __ptr_->__get(__index_); + __ptr_->__set(__index_, __val + 1); + return __val; + } + + __simd_reference operator--() && { + return std::move(*this) = __ptr_->__get(__index_) - 1; + } + + _Vp operator--(int) && { + auto __val = __ptr_->__get(__index_); + __ptr_->__set(__index_, __val - 1); + return __val; + } + + __simd_reference operator+=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) + __value; + } + + __simd_reference operator-=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) - __value; + } + + __simd_reference operator*=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) * __value; + } + + __simd_reference operator/=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) / __value; + } + + __simd_reference operator%=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) % __value; + } + + __simd_reference operator>>=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) >> __value; + } + + __simd_reference operator<<=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) << __value; + } + + __simd_reference operator&=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) & __value; + } + + __simd_reference operator|=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) | __value; + } + + __simd_reference operator^=(_Vp __value) && { + return std::move(*this) = __ptr_->__get(__index_) ^ __value; + } }; template @@ -720,6 +941,17 @@ constexpr _Tp __variadic_sum(_Up __first, _Args... __rest) { return static_cast<_Tp>(__first) + __variadic_sum<_Tp>(__rest...); } +template +struct __nodeduce { + using type = _Tp; +}; + +template +constexpr bool __vectorizable() { + return std::is_arithmetic<_Tp>::value && !std::is_const<_Tp>::value && + !std::is_volatile<_Tp>::value && !std::is_same<_Tp, bool>::value; +} + _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD_ABI @@ -728,14 +960,21 @@ using scalar = __simd_abi<_StorageKind::_Scalar, 1>; template using fixed_size = __simd_abi<_StorageKind::_Array, _Np>; -#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template -_LIBCPP_INLINE_VAR constexpr int max_fixed_size = 32; -#endif +_LIBCPP_INLINE_VAR constexpr size_t max_fixed_size = 32; + template using compatible = fixed_size<16 / sizeof(_Tp)>; + +#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION template -using native = compatible<_Tp>; +using native = __simd_abi<_StorageKind::_VecExt, + _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; +#else +template +using native = + fixed_size<_Tp, _LIBCPP_NATIVE_SIMD_WIDTH_IN_BYTES / sizeof(_Tp)>; +#endif // _LIBCPP_HAS_NO_VECTOR_EXTENSION _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD_ABI _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_SIMD @@ -749,14 +988,10 @@ struct element_aligned_tag {}; struct vector_aligned_tag {}; template struct overaligned_tag {}; -#if _LIBCPP_STD_VER > 14 _LIBCPP_INLINE_VAR constexpr element_aligned_tag element_aligned{}; _LIBCPP_INLINE_VAR constexpr vector_aligned_tag vector_aligned{}; -#if !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR constexpr overaligned_tag<_Np> overaligned{}; -#endif -#endif // traits [simd.traits] template @@ -794,7 +1029,6 @@ template struct is_simd_flag_type> : std::integral_constant {}; -#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR constexpr bool is_abi_tag_v = is_abi_tag<_Tp>::value; template @@ -804,7 +1038,6 @@ _LIBCPP_INLINE_VAR constexpr bool is_simd_mask_v = is_simd_mask<_Tp>::value; template _LIBCPP_INLINE_VAR constexpr bool is_simd_flag_type_v = is_simd_flag_type<_Tp>::value; -#endif template struct abi_for_size { using type = simd_abi::fixed_size<_Np>; @@ -824,17 +1057,16 @@ struct simd_size<_Tp, __simd_abi<__kind, _Np>> "Element type should be vectorizable"); }; +// TODO: implement it. template struct memory_alignment; -#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template > _LIBCPP_INLINE_VAR constexpr size_t simd_size_v = simd_size<_Tp, _Abi>::value; template _LIBCPP_INLINE_VAR constexpr size_t memory_alignment_v = memory_alignment<_Tp, _Up>::value; -#endif // class template simd [simd.class] template @@ -972,11 +1204,6 @@ template class where_expression; // masked assignment [simd.mask.where] -template -struct __nodeduce { - using type = _Tp; -}; - template where_expression, simd<_Tp, _Abi>> where(const typename simd<_Tp, _Abi>::mask_type&, simd<_Tp, _Abi>&) noexcept; @@ -1113,7 +1340,23 @@ public: // TODO: implement simd template class simd { +public: + using value_type = _Tp; + using reference = __simd_reference<_Tp, _Tp, _Abi>; + using mask_type = simd_mask<_Tp, _Abi>; + using abi_type = _Abi; + + simd() = default; + simd(const simd&) = default; + simd& operator=(const simd&) = default; + + static constexpr size_t size() noexcept { + return simd_size<_Tp, _Abi>::value; + } + private: + __simd_storage<_Tp, _Abi> __s_; + template static constexpr bool __can_broadcast() { return (std::is_arithmetic<_Up>::value && @@ -1126,57 +1369,97 @@ private: std::is_unsigned<_Tp>::value); } -public: - using value_type = _Tp; - // TODO: this is strawman implementation. Turn it into a proxy type. - using reference = _Tp&; - using mask_type = simd_mask<_Tp, _Abi>; - - using abi_type = _Abi; + template + static constexpr decltype( + std::forward_as_tuple(std::declval<_Generator>()( + std::integral_constant())...), + bool()) + __can_generate(std::index_sequence<__indicies...>) { + return !__variadic_sum( + !__can_broadcast()( + std::integral_constant()))>()...); + } - static constexpr size_t size() noexcept { - return simd_size<_Tp, _Abi>::value; + template + static bool __can_generate(...) { + return false; } - simd() = default; + template + void __generator_init(_Generator&& __g, std::index_sequence<__indicies...>) { + int __not_used[]{((*this)[__indicies] = + __g(std::integral_constant()), + 0)...}; + (void)__not_used; + } +public: // implicit type conversion constructor template >::value && __is_non_narrowing_arithmetic_convertible<_Up, _Tp>()>::type> - simd(const simd<_Up, simd_abi::fixed_size>&) {} + simd(const simd<_Up, simd_abi::fixed_size>& __v) { + for (size_t __i = 0; __i < size(); __i++) { + (*this)[__i] = static_cast<_Tp>(__v[__i]); + } + } // implicit broadcast constructor template ()>::type> - simd(_Up&&); + simd(_Up&& __rv) { + auto __v = static_cast<_Tp>(__rv); + for (size_t __i = 0; __i < size(); __i++) { + (*this)[__i] = __v; + } + } // generator constructor - // TODO: for now only check for the index 0. This is because C++11 doesn't - // have index_sequence, and it's hard to check for all indicies without using - // index_sequence. template ()( - std::integral_constant())), - int())()> - explicit simd(_Generator&&); + int = typename std::enable_if< + __can_generate<_Generator>(std::make_index_sequence()), + int>::type()> + explicit simd(_Generator&& __g) { + __generator_init(std::forward<_Generator>(__g), + std::make_index_sequence()); + } // load constructor - template - simd(const _Up*, _Flags); + template < + class _Up, class _Flags, + class = typename std::enable_if<__vectorizable<_Up>()>::type, + class = typename std::enable_if::value>::type> + simd(const _Up* __buffer, _Flags) { + // TODO: optimize for overaligned flags + for (size_t __i = 0; __i < size(); __i++) { + (*this)[__i] = static_cast<_Tp>(__buffer[__i]); + } + } // loads [simd.load] template - void copy_from(const _Up*, _Flags); + typename std::enable_if<__vectorizable<_Up>() && + is_simd_flag_type<_Flags>::value>::type + copy_from(const _Up* __buffer, _Flags) { + *this = simd(__buffer, _Flags()); + } // stores [simd.store] template - void copy_to(_Up*, _Flags) const; + typename std::enable_if<__vectorizable<_Up>() && + is_simd_flag_type<_Flags>::value>::type + copy_to(_Up* __buffer, _Flags) const { + // TODO: optimize for overaligned flags + for (size_t __i = 0; __i < size(); __i++) { + __buffer[__i] = static_cast<_Up>((*this)[__i]); + } + } // scalar access [simd.subscr] - reference operator[](size_t); - value_type operator[](size_t) const; + reference operator[](size_t __i) { return reference(&__s_, __i); } + + value_type operator[](size_t __i) const { return __s_.__get(__i); } // unary operators [simd.unary] simd& operator++(); @@ -1280,6 +1563,8 @@ public: friend simd_mask operator!=(const simd_mask&, const simd_mask&) noexcept; }; +#endif // _LIBCPP_STD_VER >= 17 + _LIBCPP_END_NAMESPACE_EXPERIMENTAL_SIMD #endif /* _LIBCPP_EXPERIMENTAL_SIMD */ diff --git a/test/std/experimental/simd/simd.abi/vector_extension.pass.cpp b/test/std/experimental/simd/simd.abi/vector_extension.pass.cpp new file mode 100644 index 000000000..dd8436618 --- /dev/null +++ b/test/std/experimental/simd/simd.abi/vector_extension.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// [simd.abi] + +#include +#include + +namespace ex = std::experimental::parallelism_v2; + +constexpr inline int reg_width() { +#if defined(__AVX__) + return 32; +#else + return 16; +#endif +} + +#ifndef _LIBCPP_HAS_NO_VECTOR_EXTENSION + +static_assert( + sizeof(ex::simd>) == 1, + ""); +static_assert( + sizeof(ex::simd>) == 2, + ""); +static_assert( + sizeof(ex::simd>) == 4, + ""); +static_assert( + sizeof(ex::simd>) == 16, + ""); +static_assert( + sizeof(ex::simd>) == + 16, + ""); +static_assert( + sizeof(ex::simd>) == + 32, + ""); +static_assert( + std::is_same, + ex::__simd_abi>::value, + ""); +#else +static_assert( + std::is_same, + ex::__simd_abi>::value, + ""); + +#endif + +static_assert(std::is_same, + ex::__simd_abi>::value, + ""); + +int main() {} diff --git a/test/std/experimental/simd/simd.access/default.pass.cpp b/test/std/experimental/simd/simd.access/default.pass.cpp new file mode 100644 index 000000000..697035b66 --- /dev/null +++ b/test/std/experimental/simd/simd.access/default.pass.cpp @@ -0,0 +1,217 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// scalar access [simd.subscr] +// reference operator[](size_t); +// value_type operator[](size_t) const; + +#include +#include +#include + +namespace ex = std::experimental::parallelism_v2; + +template +void test_access() { + { + SimdType a(42), b(4); + static_assert(std::is_convertible::value, ""); + + assert(a[0] == 42); + assert(!a[0] == !42); + assert(~a[0] == ~42); + assert(+a[0] == +42); + assert(-a[0] == -42); + assert(a[0] + b[0] == 42 + 4); + assert(a[0] - b[0] == 42 - 4); + assert(a[0] * b[0] == 42 * 4); + assert(a[0] / b[0] == 42 / 4); + assert(a[0] % b[0] == 42 % 4); + assert(a[0] << b[0] == (42 << 4)); + assert(a[0] >> b[0] == (42 >> 4)); + assert(a[0] < b[0] == false); + assert(a[0] <= b[0] == false); + assert(a[0] > b[0] == true); + assert(a[0] >= b[0] == true); + assert(a[0] == b[0] == false); + assert(a[0] != b[0] == true); + assert((a[0] & b[0]) == (42 & 4)); + assert((a[0] | b[0]) == (42 | 4)); + assert((a[0] ^ b[0]) == (42 ^ 4)); + assert((a[0] && b[0]) == true); + assert((a[0] || b[0]) == true); + + { + auto c = a; + ++c[0]; + assert(c[0] == 42 + 1); + assert(c[1] == 42); + } + { + auto c = a; + auto ret = c[0]++; + assert(ret == 42); + assert(c[0] == 42 + 1); + assert(c[1] == 42); + } + { + auto c = a; + --c[0]; + assert(c[0] == 42 - 1); + assert(c[1] == 42); + } + { + auto c = a; + auto ret = c[0]--; + assert(ret == 42); + assert(c[0] == 42 - 1); + assert(c[1] == 42); + } + + { + auto c = a; + c[0] += b[0]; + assert(c[0] == 42 + 4); + assert(c[1] == 42); + } + { + auto c = a; + c[0] -= b[0]; + assert(c[0] == 42 - 4); + assert(c[1] == 42); + } + { + auto c = a; + c[0] *= b[0]; + assert(c[0] == 42 * 4); + assert(c[1] == 42); + } + { + auto c = a; + c[0] /= b[0]; + assert(c[0] == 42 / 4); + assert(c[1] == 42); + } + { + auto c = a; + c[0] %= b[0]; + assert(c[0] == 42 % 4); + assert(c[1] == 42); + } + { + auto c = a; + c[0] >>= b[0]; + assert(c[0] == (42 >> 4)); + assert(c[1] == 42); + } + { + auto c = a; + c[0] <<= b[0]; + assert(c[0] == (42 << 4)); + assert(c[1] == 42); + } + { + auto c = a; + c[0] &= b[0]; + assert(c[0] == (42 & 4)); + assert(c[1] == 42); + } + { + auto c = a; + c[0] |= b[0]; + assert(c[0] == (42 | 4)); + assert(c[1] == 42); + } + { + auto c = a; + c[0] ^= b[0]; + assert(c[0] == (42 ^ 4)); + assert(c[1] == 42); + } + + { + auto c = a; + (void)(a[0] + (c[0] += a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] -= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] *= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] /= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] %= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] >>= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] <<= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] &= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] |= a[0])); + } + { + auto c = a; + (void)(a[0] + (c[0] ^= a[0])); + } + } + { + const SimdType a(42); + const SimdType b(4); + static_assert(std::is_same::value, ""); + + assert(a[0] == 42); + assert(!a[0] == !42); + assert(~a[0] == ~42); + assert(+a[0] == +42); + assert(-a[0] == -42); + assert(a[0] + b[0] == 42 + 4); + assert(a[0] - b[0] == 42 - 4); + assert(a[0] * b[0] == 42 * 4); + assert(a[0] / b[0] == 42 / 4); + assert(a[0] % b[0] == 42 % 4); + assert(a[0] << b[0] == (42 << 4)); + assert(a[0] >> b[0] == (42 >> 4)); + assert(a[0] < b[0] == false); + assert(a[0] <= b[0] == false); + assert(a[0] > b[0] == true); + assert(a[0] >= b[0] == true); + assert(a[0] == b[0] == false); + assert(a[0] != b[0] == true); + assert((a[0] & b[0]) == (42 & 4)); + assert((a[0] | b[0]) == (42 | 4)); + assert((a[0] ^ b[0]) == (42 ^ 4)); + assert((a[0] && b[0]) == true); + assert((a[0] || b[0]) == true); + } +} + +int main() { + test_access>(); + test_access>(); +} diff --git a/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp b/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp index af6b13fe8..d15f138d5 100644 --- a/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp +++ b/test/std/experimental/simd/simd.casts/simd_cast.pass.cpp @@ -7,34 +7,40 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.casts] -// template see below simd_cast(const simd&); +// template see below ex::simd_cast<(const +// ex::simd&); + #include #include -using namespace std::experimental::parallelism_v2; - -static_assert(std::is_same(native_simd())), - native_simd>::value, - ""); +namespace ex = std::experimental::parallelism_v2; static_assert( - std::is_same(fixed_size_simd())), - fixed_size_simd>::value, + std::is_same(ex::native_simd())), + ex::native_simd>::value, ""); -static_assert(std::is_same>( - simd())), - fixed_size_simd>::value, +static_assert(std::is_same( + ex::fixed_size_simd())), + ex::fixed_size_simd>::value, ""); -static_assert(std::is_same>( - fixed_size_simd())), - simd>::value, - ""); +static_assert( + std::is_same>( + ex::simd())), + ex::fixed_size_simd>::value, + ""); + +static_assert( + std::is_same< + decltype(ex::simd_cast>( + ex::fixed_size_simd())), + ex::simd>::value, + ""); int main() {} diff --git a/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp b/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp index eb1fa55e0..b73466477 100644 --- a/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp +++ b/test/std/experimental/simd/simd.casts/static_simd_cast.pass.cpp @@ -7,32 +7,35 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.casts] -// template see below static_simd_cast(const simd&); +// template see below ex::static_simd_cast<(const +// ex::simd&); #include #include -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; static_assert( - std::is_same(native_simd())), - native_simd>::value, + std::is_same(ex::native_simd())), + ex::native_simd>::value, ""); -static_assert(std::is_same>( - simd())), - fixed_size_simd>::value, - ""); +static_assert( + std::is_same>( + ex::simd())), + ex::fixed_size_simd>::value, + ""); static_assert( - std::is_same>( - fixed_size_simd())), - simd>::value, + std::is_same< + decltype(ex::static_simd_cast>( + ex::fixed_size_simd())), + ex::simd>::value, ""); int main() {} diff --git a/test/std/experimental/simd/simd.cons/broadcast.pass.cpp b/test/std/experimental/simd/simd.cons/broadcast.pass.cpp index 60230cc63..49b2b5572 100644 --- a/test/std/experimental/simd/simd.cons/broadcast.pass.cpp +++ b/test/std/experimental/simd/simd.cons/broadcast.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // See GCC PR63723. // UNSUPPORTED: gcc-4.9 @@ -20,18 +20,19 @@ #include #include -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; template auto not_supported_native_simd_ctor(Args&&... args) - -> decltype(native_simd(std::forward(args)...), void()) = delete; + -> decltype(ex::native_simd(std::forward(args)...), + void()) = delete; template void not_supported_native_simd_ctor(...) {} template auto supported_native_simd_ctor(Args&&... args) - -> decltype(native_simd(std::forward(args)...), void()) {} + -> decltype(ex::native_simd(std::forward(args)...), void()) {} template void supported_native_simd_ctor(...) = delete; @@ -55,4 +56,31 @@ void compile_narrowing_conversion() { not_supported_native_simd_ctor(3.); } -int main() {} +void compile_convertible() { + struct ConvertibleToInt { + operator int64_t() const; + }; + supported_native_simd_ctor(ConvertibleToInt()); + + struct NotConvertibleToInt {}; + not_supported_native_simd_ctor(NotConvertibleToInt()); +} + +void compile_unsigned() { + not_supported_native_simd_ctor(3u); + supported_native_simd_ctor(3u); +} + +template +void test_broadcast() { + SimdType a(3); + for (size_t i = 0; i < a.size(); i++) { + assert(a[i] == 3); + } +} + +int main() { + test_broadcast>(); + test_broadcast>(); + test_broadcast>(); +} diff --git a/test/std/experimental/simd/simd.cons/default.pass.cpp b/test/std/experimental/simd/simd.cons/default.pass.cpp new file mode 100644 index 000000000..0f12eced0 --- /dev/null +++ b/test/std/experimental/simd/simd.cons/default.pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// [simd.class] +// simd() = default; + +#include +#include + +namespace ex = std::experimental::parallelism_v2; + +int main() { + static_assert(ex::native_simd().size() > 0, ""); + static_assert(ex::fixed_size_simd().size() == 4, ""); + static_assert(ex::fixed_size_simd().size() == 5, ""); + static_assert(ex::fixed_size_simd().size() == 1, ""); + static_assert(ex::fixed_size_simd().size() == 32, ""); +} diff --git a/test/std/experimental/simd/simd.cons/generator.pass.cpp b/test/std/experimental/simd/simd.cons/generator.pass.cpp index baf7d936c..43273e896 100644 --- a/test/std/experimental/simd/simd.cons/generator.pass.cpp +++ b/test/std/experimental/simd/simd.cons/generator.pass.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // See GCC PR63723. // UNSUPPORTED: gcc-4.9 @@ -17,30 +17,75 @@ // [simd.class] // template explicit simd(G&& gen); -#include #include +#include -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; template -auto not_supported_native_simd_ctor(Args&&... args) - -> decltype(native_simd(std::forward(args)...), void()) = delete; +auto not_supported_simd128_ctor(Args&&... args) -> decltype( + ex::fixed_size_simd(std::forward(args)...), + void()) = delete; template -void not_supported_native_simd_ctor(...) {} +void not_supported_simd128_ctor(...) {} template -auto supported_native_simd_ctor(Args&&... args) - -> decltype(native_simd(std::forward(args)...), void()) {} +auto supported_simd128_ctor(Args&&... args) -> decltype( + ex::fixed_size_simd(std::forward(args)...), + void()) {} template -void supported_native_simd_ctor(...) = delete; +void supported_simd128_ctor(...) = delete; + +struct identity { + template + int operator()(std::integral_constant) const { + return value; + } +}; void compile_generator() { - supported_native_simd_ctor([](int i) { return i; }); - not_supported_native_simd_ctor([](int i) { return float(i); }); - not_supported_native_simd_ctor([](intptr_t i) { return (int*)(i); }); - not_supported_native_simd_ctor([](int* i) { return i; }); + supported_simd128_ctor(identity()); + not_supported_simd128_ctor([](int i) { return float(i); }); + not_supported_simd128_ctor([](intptr_t i) { return (int*)(i); }); + not_supported_simd128_ctor([](int* i) { return i; }); } -int main() {} +struct limited_identity { + template + typename std::conditional::type + operator()(std::integral_constant) const { + return value; + } +}; + +void compile_limited_identity() { + supported_simd128_ctor(limited_identity()); + not_supported_simd128_ctor(limited_identity()); +} + +template +void test_generator() { + { + SimdType a([](int i) { return i; }); + assert(a[0] == 0); + assert(a[1] == 1); + assert(a[2] == 2); + assert(a[3] == 3); + } + { + SimdType a([](int i) { return 2 * i - 1; }); + assert(a[0] == -1); + assert(a[1] == 1); + assert(a[2] == 3); + assert(a[3] == 5); + } +} + +int main() { + // TODO: adjust the tests when this assertion fails. + assert(ex::native_simd::size() >= 4); + test_generator>(); + test_generator>(); +} diff --git a/test/std/experimental/simd/simd.cons/load.pass.cpp b/test/std/experimental/simd/simd.cons/load.pass.cpp new file mode 100644 index 000000000..8c87fe7a5 --- /dev/null +++ b/test/std/experimental/simd/simd.cons/load.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// [simd.class] +// template simd(const U* mem, Flags f); + +#include +#include + +#include "test_macros.h" + +namespace ex = std::experimental::parallelism_v2; + +template +auto not_supported_native_simd_ctor(Args&&... args) + -> decltype(ex::native_simd(std::forward(args)...), + void()) = delete; + +template +void not_supported_native_simd_ctor(...) {} + +template +auto supported_native_simd_ctor(Args&&... args) + -> decltype(ex::native_simd(std::forward(args)...), void()) {} + +template +void supported_native_simd_ctor(...) = delete; + +void compile_load_ctor() { + supported_native_simd_ctor((int*)nullptr, ex::element_aligned_tag()); + supported_native_simd_ctor((int*)nullptr, + ex::element_aligned_tag()); + supported_native_simd_ctor((float*)nullptr, + ex::element_aligned_tag()); + supported_native_simd_ctor((unsigned int*)nullptr, + ex::element_aligned_tag()); + supported_native_simd_ctor((float*)nullptr, + ex::element_aligned_tag()); + + not_supported_native_simd_ctor((int*)nullptr, int()); +} + +template +void test_load_ctor() { + alignas(32) int32_t buffer[] = {4, 3, 2, 1}; + { + SimdType a(buffer, ex::element_aligned_tag()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a(buffer, ex::vector_aligned_tag()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a(buffer, ex::overaligned_tag<32>()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + + { + SimdType a(buffer, ex::element_aligned); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a(buffer, ex::vector_aligned); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a(buffer, ex::overaligned<32>); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } +} + +template +void test_converting_load_ctor() { + float buffer[] = {1., 2., 4., 8.}; + SimdType a(buffer, ex::element_aligned_tag()); + assert(a[0] == 1); + assert(a[1] == 2); + assert(a[2] == 4); + assert(a[3] == 8); +} + +int main() { + // TODO: adjust the tests when this assertion fails. + assert(ex::native_simd::size() >= 4); + test_load_ctor>(); + test_load_ctor>(); + test_converting_load_ctor>(); + test_converting_load_ctor>(); +} diff --git a/test/std/experimental/simd/simd.mem/load.pass.cpp b/test/std/experimental/simd/simd.mem/load.pass.cpp new file mode 100644 index 000000000..b1a3a2b1d --- /dev/null +++ b/test/std/experimental/simd/simd.mem/load.pass.cpp @@ -0,0 +1,122 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// loads [simd.load] +// template void copy_from(const U* mem, Flags f); + +#include +#include + +#include "test_macros.h" + +namespace ex = std::experimental::parallelism_v2; + +template +auto not_supported_load(Args&&... args) -> decltype( + std::declval>().copy_from(std::forward(args)...), + void()) = delete; + +template +void not_supported_load(...) {} + +template +auto supported_load(Args&&... args) -> decltype( + std::declval>().copy_from(std::forward(args)...), + void()) {} + +template +void supported_load(...) = delete; + +void compile_load() { + supported_load((int*)nullptr, ex::element_aligned_tag()); + supported_load((int*)nullptr, ex::element_aligned_tag()); + supported_load((float*)nullptr, ex::element_aligned_tag()); + supported_load((unsigned int*)nullptr, ex::element_aligned_tag()); + supported_load((float*)nullptr, ex::element_aligned_tag()); + + not_supported_load((int*)nullptr, int()); +} + +template +void test_load() { + alignas(32) int32_t buffer[] = {4, 3, 2, 1}; + { + SimdType a; + a.copy_from(buffer, ex::element_aligned_tag()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a; + a.copy_from(buffer, ex::vector_aligned_tag()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a; + a.copy_from(buffer, ex::overaligned_tag<32>()); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + + { + SimdType a; + a.copy_from(buffer, ex::element_aligned); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a; + a.copy_from(buffer, ex::vector_aligned); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } + { + SimdType a; + a.copy_from(buffer, ex::overaligned<32>); + assert(a[0] == 4); + assert(a[1] == 3); + assert(a[2] == 2); + assert(a[3] == 1); + } +} + +template +void test_converting_load() { + float buffer[] = {1., 2., 4., 8.}; + SimdType a; + a.copy_from(buffer, ex::element_aligned_tag()); + assert(a[0] == 1); + assert(a[1] == 2); + assert(a[2] == 4); + assert(a[3] == 8); +} + +int main() { + // TODO: adjust the tests when this assertion fails. + assert(ex::native_simd::size() >= 4); + test_load>(); + test_load>(); + test_converting_load>(); + test_converting_load>(); +} diff --git a/test/std/experimental/simd/simd.mem/store.pass.cpp b/test/std/experimental/simd/simd.mem/store.pass.cpp new file mode 100644 index 000000000..2025a79f2 --- /dev/null +++ b/test/std/experimental/simd/simd.mem/store.pass.cpp @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// +// +// // stores [simd.store] +// template void copy_to(U* mem, Flags f) const; + +#include +#include + +#include "test_macros.h" + +namespace ex = std::experimental::parallelism_v2; + +template +void test_store() { + SimdType a([](int i) { return 4 - i; }); + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::element_aligned_tag()); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::vector_aligned_tag()); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::overaligned_tag<32>()); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } + + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::element_aligned); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::vector_aligned); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } + { + alignas(32) int32_t buffer[4] = {0}; + a.copy_to(buffer, ex::overaligned<32>); + assert(buffer[0] == 4); + assert(buffer[1] == 3); + assert(buffer[2] == 2); + assert(buffer[3] == 1); + } +} + +template +void test_converting_store() { + float buffer[4] = {0.}; + SimdType a([](int i) { return 1 << i; }); + a.copy_to(buffer, ex::element_aligned_tag()); + assert(buffer[0] == 1.); + assert(buffer[1] == 2.); + assert(buffer[2] == 4.); + assert(buffer[3] == 8.); +} + +int main() { + // TODO: adjust the tests when this assertion fails. + test_store>(); + test_store>(); + test_converting_store>(); + test_converting_store>(); +} diff --git a/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp b/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp index 6e244220d..b3cd92add 100644 --- a/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp +++ b/test/std/experimental/simd/simd.traits/abi_for_size.pass.cpp @@ -7,24 +7,26 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.traits] -// template struct abi_for_size { using type = see below ; }; -// template using abi_for_size_t = typename abi_for_size::type; +// template struct abi_for_size { using type = see below ; +// }; template using ex::abi_for_size_t = typename +// ex::abi_for_size::type; #include #include -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; -static_assert(std::is_same::type, - simd_abi::fixed_size<4>>::value, +static_assert(std::is_same::type, + ex::simd_abi::fixed_size<4>>::value, ""); -static_assert( - std::is_same, simd_abi::fixed_size<4>>::value, ""); +static_assert(std::is_same, + ex::simd_abi::fixed_size<4>>::value, + ""); int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp b/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp index 4f4f738a8..e87eafbdb 100644 --- a/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_abi_tag.pass.cpp @@ -7,109 +7,107 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.traits] // template struct is_abi_tag; -// template inline constexpr bool is_abi_tag_v = is_abi_tag::value; +// template inline constexpr bool ex::is_abi_tag_v = +// ex::is_abi_tag::value; #include #include #include "test_macros.h" -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; struct UserType {}; -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); - -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); - -static_assert( is_abi_tag::value, ""); -static_assert(!std::is_same>::value, - ""); - -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); -static_assert( is_abi_tag>::value, ""); - -static_assert(!is_abi_tag::value, ""); -static_assert(!is_abi_tag::value, ""); -static_assert(!is_abi_tag::value, ""); -static_assert(!is_abi_tag::value, ""); -static_assert(!is_abi_tag>::value, ""); -static_assert(!is_abi_tag>::value, ""); -static_assert(!is_abi_tag>::value, ""); -static_assert(!is_abi_tag>::value, ""); - -#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ - !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) - -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); - -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); - -static_assert( is_abi_tag_v, ""); -static_assert(!std::is_same>::value, - ""); - -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); -static_assert( is_abi_tag_v>, ""); - -static_assert(!is_abi_tag_v, ""); -static_assert(!is_abi_tag_v, ""); -static_assert(!is_abi_tag_v, ""); -static_assert(!is_abi_tag_v, ""); -static_assert(!is_abi_tag_v>, ""); -static_assert(!is_abi_tag_v>, ""); -static_assert(!is_abi_tag_v>, ""); -static_assert(!is_abi_tag_v>, ""); - -#endif +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); + +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); + +static_assert(ex::is_abi_tag::value, ""); +static_assert( + !std::is_same>::value, + ""); + +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); +static_assert(ex::is_abi_tag>::value, ""); + +static_assert(!ex::is_abi_tag::value, ""); +static_assert(!ex::is_abi_tag::value, ""); +static_assert(!ex::is_abi_tag::value, ""); +static_assert(!ex::is_abi_tag::value, ""); +static_assert(!ex::is_abi_tag>::value, ""); +static_assert(!ex::is_abi_tag>::value, ""); +static_assert(!ex::is_abi_tag>::value, ""); +static_assert(!ex::is_abi_tag>::value, ""); + +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); + +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); + +static_assert(ex::is_abi_tag_v, ""); +static_assert( + !std::is_same>::value, + ""); + +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); +static_assert(ex::is_abi_tag_v>, ""); + +static_assert(!ex::is_abi_tag_v, ""); +static_assert(!ex::is_abi_tag_v, ""); +static_assert(!ex::is_abi_tag_v, ""); +static_assert(!ex::is_abi_tag_v, ""); +static_assert(!ex::is_abi_tag_v>, ""); +static_assert(!ex::is_abi_tag_v>, ""); +static_assert(!ex::is_abi_tag_v>, ""); +static_assert(!ex::is_abi_tag_v>, ""); int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_simd.pass.cpp b/test/std/experimental/simd/simd.traits/is_simd.pass.cpp index 77f5d10ed..8d7c0946c 100644 --- a/test/std/experimental/simd/simd.traits/is_simd.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_simd.pass.cpp @@ -7,127 +7,123 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.traits] -// template struct is_simd; -// template inline constexpr bool is_simd_v = is_simd::value; +// template struct ex::is_simd; +// template inline constexpr bool ex::is_simd_v = +// ex::is_simd::value; #include #include #include "test_macros.h" -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; struct UserType {}; -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); - -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); - -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); - -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); -static_assert( is_simd>::value, ""); - -static_assert(!is_simd::value, ""); -static_assert(!is_simd::value, ""); -static_assert(!is_simd::value, ""); -static_assert(!is_simd>::value, ""); -static_assert(!is_simd>::value, ""); -static_assert(!is_simd::value, ""); - -#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ - !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) - -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); - -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); - -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); - -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); -static_assert( is_simd_v>, ""); - -static_assert(!is_simd_v, ""); -static_assert(!is_simd_v, ""); -static_assert(!is_simd_v, ""); -static_assert(!is_simd_v>, ""); -static_assert(!is_simd_v>, ""); -static_assert(!is_simd_v, ""); - -#endif +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); + +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); + +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); + +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); +static_assert(ex::is_simd>::value, ""); + +static_assert(!ex::is_simd::value, ""); +static_assert(!ex::is_simd::value, ""); +static_assert(!ex::is_simd::value, ""); +static_assert(!ex::is_simd>::value, ""); +static_assert(!ex::is_simd>::value, ""); +static_assert(!ex::is_simd::value, ""); + +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); + +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); + +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); + +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); +static_assert(ex::is_simd_v>, ""); + +static_assert(!ex::is_simd_v, ""); +static_assert(!ex::is_simd_v, ""); +static_assert(!ex::is_simd_v, ""); +static_assert(!ex::is_simd_v>, ""); +static_assert(!ex::is_simd_v>, ""); +static_assert(!ex::is_simd_v, ""); int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp b/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp index a6fe40905..ecb68fb62 100644 --- a/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_simd_flag_type.pass.cpp @@ -7,49 +7,45 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.traits] // template struct is_simd_flag_type; -// template inline constexpr bool is_simd_flag_type_v = is_simd_flag_type::value; +// template inline constexpr bool ex::is_simd_flag_type_v = +// ex::is_simd_flag_type::value; #include #include #include "test_macros.h" -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; struct UserType {}; -static_assert( is_simd_flag_type::value, ""); -static_assert( is_simd_flag_type::value, ""); -static_assert( is_simd_flag_type>::value, ""); -static_assert( is_simd_flag_type>::value, ""); - -static_assert(!is_simd_flag_type::value, ""); -static_assert(!is_simd_flag_type::value, ""); -static_assert(!is_simd_flag_type::value, ""); -static_assert(!is_simd_flag_type::value, ""); -static_assert(!is_simd_flag_type>::value, ""); -static_assert(!is_simd_flag_type>::value, ""); - -#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ - !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) - -static_assert( is_simd_flag_type_v, ""); -static_assert( is_simd_flag_type_v, ""); -static_assert( is_simd_flag_type_v>, ""); -static_assert( is_simd_flag_type_v>, ""); - -static_assert(!is_simd_flag_type_v, ""); -static_assert(!is_simd_flag_type_v, ""); -static_assert(!is_simd_flag_type_v, ""); -static_assert(!is_simd_flag_type_v, ""); -static_assert(!is_simd_flag_type_v>, ""); -static_assert(!is_simd_flag_type_v>, ""); - -#endif +static_assert(ex::is_simd_flag_type::value, ""); +static_assert(ex::is_simd_flag_type::value, ""); +static_assert(ex::is_simd_flag_type>::value, ""); +static_assert(ex::is_simd_flag_type>::value, ""); + +static_assert(!ex::is_simd_flag_type::value, ""); +static_assert(!ex::is_simd_flag_type::value, ""); +static_assert(!ex::is_simd_flag_type::value, ""); +static_assert(!ex::is_simd_flag_type::value, ""); +static_assert(!ex::is_simd_flag_type>::value, ""); +static_assert(!ex::is_simd_flag_type>::value, ""); + +static_assert(ex::is_simd_flag_type_v, ""); +static_assert(ex::is_simd_flag_type_v, ""); +static_assert(ex::is_simd_flag_type_v>, ""); +static_assert(ex::is_simd_flag_type_v>, ""); + +static_assert(!ex::is_simd_flag_type_v, ""); +static_assert(!ex::is_simd_flag_type_v, ""); +static_assert(!ex::is_simd_flag_type_v, ""); +static_assert(!ex::is_simd_flag_type_v, ""); +static_assert(!ex::is_simd_flag_type_v>, ""); +static_assert(!ex::is_simd_flag_type_v>, ""); int main() {} diff --git a/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp b/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp index 8c2e0ed5b..736802443 100644 --- a/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp +++ b/test/std/experimental/simd/simd.traits/is_simd_mask.pass.cpp @@ -7,127 +7,146 @@ // //===----------------------------------------------------------------------===// -// UNSUPPORTED: c++98, c++03 +// UNSUPPORTED: c++98, c++03, c++11, c++14 // // // [simd.traits] -// template struct is_simd_mask; -// template inline constexpr bool is_simd_mask_v = is_simd_mask::value; +// template struct ex::is_simd_mask; +// template inline constexpr bool ex::is_simd_mask_v = +// ex::is_simd_mask::value; #include #include #include "test_macros.h" -using namespace std::experimental::parallelism_v2; +namespace ex = std::experimental::parallelism_v2; struct UserType {}; -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); - -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); - -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); - -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); -static_assert( is_simd_mask>::value, ""); - -static_assert(!is_simd_mask::value, ""); -static_assert(!is_simd_mask::value, ""); -static_assert(!is_simd_mask::value, ""); -static_assert(!is_simd_mask>::value, ""); -static_assert(!is_simd_mask>::value, ""); -static_assert(!is_simd_mask::value, ""); - -#if TEST_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) && \ - !defined(_LIBCPP_HAS_NO_INLINE_VARIABLES) - -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); - -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); - -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); - -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); -static_assert( is_simd_mask_v>, ""); - -static_assert(!is_simd_mask_v, ""); -static_assert(!is_simd_mask_v, ""); -static_assert(!is_simd_mask_v, ""); -static_assert(!is_simd_mask_v>, ""); -static_assert(!is_simd_mask_v>, ""); -static_assert(!is_simd_mask_v, ""); - -#endif +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); + +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); + +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, ""); + +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, + ""); +static_assert(ex::is_simd_mask>::value, ""); +static_assert(ex::is_simd_mask>::value, + ""); + +static_assert(!ex::is_simd_mask::value, ""); +static_assert(!ex::is_simd_mask::value, ""); +static_assert(!ex::is_simd_mask::value, ""); +static_assert(!ex::is_simd_mask>::value, ""); +static_assert(!ex::is_simd_mask>::value, ""); +static_assert(!ex::is_simd_mask::value, ""); + +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); + +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); + +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); + +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); +static_assert(ex::is_simd_mask_v>, ""); + +static_assert(!ex::is_simd_mask_v, ""); +static_assert(!ex::is_simd_mask_v, ""); +static_assert(!ex::is_simd_mask_v, ""); +static_assert(!ex::is_simd_mask_v>, ""); +static_assert(!ex::is_simd_mask_v>, ""); +static_assert(!ex::is_simd_mask_v, ""); int main() {} -- GitLab From 379cbeb1a2c73c8da006aa065b59b20cb893d95a Mon Sep 17 00:00:00 2001 From: Tim Shen Date: Mon, 30 Jul 2018 23:05:40 +0000 Subject: [PATCH 111/495] [libcxx] fix `>> 42` UB in git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338325 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/std/experimental/simd/simd.access/default.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/std/experimental/simd/simd.access/default.pass.cpp b/test/std/experimental/simd/simd.access/default.pass.cpp index 697035b66..6ce32cab8 100644 --- a/test/std/experimental/simd/simd.access/default.pass.cpp +++ b/test/std/experimental/simd/simd.access/default.pass.cpp @@ -161,7 +161,7 @@ void test_access() { } { auto c = a; - (void)(a[0] + (c[0] >>= a[0])); + (void)(a[0] + (c[0] >>= b[0])); } { auto c = a; -- GitLab From decf28e84f33e3f0fd1cf5e7a6d6d191d8249857 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 30 Jul 2018 23:33:48 +0000 Subject: [PATCH 112/495] Code cleanup - change naked 'throw' expressions to call helpre function '__throw_future_error'. The behavior change is that if you build libc++ with exceptions disabled, and then use that in a program that sets the value of the future twice (for example), it will now abort instead of behaving unpredictably. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338332 91177308-0d34-0410-b5e6-96231b3b80d8 --- src/future.cpp | 44 +++++++++++--------------------------------- 1 file changed, 11 insertions(+), 33 deletions(-) diff --git a/src/future.cpp b/src/future.cpp index e1758f39d..07e4602f5 100644 --- a/src/future.cpp +++ b/src/future.cpp @@ -92,10 +92,8 @@ void __assoc_sub_state::set_value() { unique_lock __lk(__mut_); -#ifndef _LIBCPP_NO_EXCEPTIONS if (__has_value()) - throw future_error(make_error_code(future_errc::promise_already_satisfied)); -#endif + __throw_future_error(future_errc::promise_already_satisfied); __state_ |= __constructed | ready; __cv_.notify_all(); } @@ -104,10 +102,8 @@ void __assoc_sub_state::set_value_at_thread_exit() { unique_lock __lk(__mut_); -#ifndef _LIBCPP_NO_EXCEPTIONS if (__has_value()) - throw future_error(make_error_code(future_errc::promise_already_satisfied)); -#endif + __throw_future_error(future_errc::promise_already_satisfied); __state_ |= __constructed; __thread_local_data()->__make_ready_at_thread_exit(this); } @@ -116,10 +112,8 @@ void __assoc_sub_state::set_exception(exception_ptr __p) { unique_lock __lk(__mut_); -#ifndef _LIBCPP_NO_EXCEPTIONS if (__has_value()) - throw future_error(make_error_code(future_errc::promise_already_satisfied)); -#endif + __throw_future_error(future_errc::promise_already_satisfied); __exception_ = __p; __state_ |= ready; __cv_.notify_all(); @@ -129,10 +123,8 @@ void __assoc_sub_state::set_exception_at_thread_exit(exception_ptr __p) { unique_lock __lk(__mut_); -#ifndef _LIBCPP_NO_EXCEPTIONS if (__has_value()) - throw future_error(make_error_code(future_errc::promise_already_satisfied)); -#endif + __throw_future_error(future_errc::promise_already_satisfied); __exception_ = __p; __thread_local_data()->__make_ready_at_thread_exit(this); } @@ -181,18 +173,14 @@ __assoc_sub_state::__sub_wait(unique_lock& __lk) void __assoc_sub_state::__execute() { -#ifndef _LIBCPP_NO_EXCEPTIONS - throw future_error(make_error_code(future_errc::no_state)); -#endif + __throw_future_error(future_errc::no_state); } future::future(__assoc_sub_state* __state) : __state_(__state) { -#ifndef _LIBCPP_NO_EXCEPTIONS if (__state_->__has_future_attached()) - throw future_error(make_error_code(future_errc::future_already_retrieved)); -#endif + __throw_future_error(future_errc::future_already_retrieved); __state_->__add_shared(); __state_->__set_future_attached(); } @@ -234,50 +222,40 @@ promise::~promise() future promise::get_future() { -#ifndef _LIBCPP_NO_EXCEPTIONS if (__state_ == nullptr) - throw future_error(make_error_code(future_errc::no_state)); -#endif + __throw_future_error(future_errc::no_state); return future(__state_); } void promise::set_value() { -#ifndef _LIBCPP_NO_EXCEPTIONS if (__state_ == nullptr) - throw future_error(make_error_code(future_errc::no_state)); -#endif + __throw_future_error(future_errc::no_state); __state_->set_value(); } void promise::set_exception(exception_ptr __p) { -#ifndef _LIBCPP_NO_EXCEPTIONS if (__state_ == nullptr) - throw future_error(make_error_code(future_errc::no_state)); -#endif + __throw_future_error(future_errc::no_state); __state_->set_exception(__p); } void promise::set_value_at_thread_exit() { -#ifndef _LIBCPP_NO_EXCEPTIONS if (__state_ == nullptr) - throw future_error(make_error_code(future_errc::no_state)); -#endif + __throw_future_error(future_errc::no_state); __state_->set_value_at_thread_exit(); } void promise::set_exception_at_thread_exit(exception_ptr __p) { -#ifndef _LIBCPP_NO_EXCEPTIONS if (__state_ == nullptr) - throw future_error(make_error_code(future_errc::no_state)); -#endif + __throw_future_error(future_errc::no_state); __state_->set_exception_at_thread_exit(__p); } -- GitLab From 1bef51a0b59ad0e8b135f6ac7f57f7690e57f06c Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 31 Jul 2018 18:23:57 +0000 Subject: [PATCH 113/495] Introduce a new test macro TEST_HAS_C11_FEATURES which is set when the underlying C library has C11 features. In C++17, we use those features. <__config> defines a similar macro, _LIBCPP_HAS_C11_FEATURES, but we don't want to use that in the library-independent parts of the tests, so define the new one. Also add a libc++-specific test to make sure the two stay in sync. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338411 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../has_c11_features.pass.cpp | 29 ++++++++++++ test/support/test_macros.h | 47 +++++++++++++++---- 2 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 test/libcxx/language.support/has_c11_features.pass.cpp diff --git a/test/libcxx/language.support/has_c11_features.pass.cpp b/test/libcxx/language.support/has_c11_features.pass.cpp new file mode 100644 index 000000000..cdccc00e2 --- /dev/null +++ b/test/libcxx/language.support/has_c11_features.pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// We have two macros for checking whether or not the underlying C library +// has C11 features: +// TEST_HAS_C11_FEATURES - which is defined in "test_macros.h" +// _LIBCPP_HAS_C11_FEATURES - which is defined in <__config> +// They should always be the same + +#ifdef TEST_HAS_C11_FEATURES +# ifndef _LIBCPP_HAS_C11_FEATURES +# error "TEST_HAS_C11_FEATURES is defined, but _LIBCPP_HAS_C11_FEATURES is not" +# endif +#endif + +#ifdef _LIBCPP_HAS_C11_FEATURES +# ifndef TEST_HAS_C11_FEATURES +# error "_LIBCPP_HAS_C11_FEATURES is defined, but TEST_HAS_C11_FEATURES is not" +# endif +#endif + +int main() {} diff --git a/test/support/test_macros.h b/test/support/test_macros.h index dbbfd5309..ac6ec79b9 100644 --- a/test/support/test_macros.h +++ b/test/support/test_macros.h @@ -94,16 +94,6 @@ #define TEST_GLIBC_PREREQ(major, minor) __GLIBC_PREREQ(major, minor) #endif -/* Features that were introduced in C++14 */ -#if TEST_STD_VER >= 14 -#define TEST_HAS_EXTENDED_CONSTEXPR -#define TEST_HAS_VARIABLE_TEMPLATES -#endif - -/* Features that were introduced after C++14 */ -#if TEST_STD_VER > 14 -#endif - #if TEST_STD_VER >= 11 #define TEST_ALIGNOF(...) alignof(__VA_ARGS__) #define TEST_ALIGNAS(...) alignas(__VA_ARGS__) @@ -132,6 +122,43 @@ #define TEST_THROW_SPEC(...) throw(__VA_ARGS__) #endif +// Sniff out to see if the underling C library has C11 features +// Note that at this time (July 2018), MacOS X and iOS do NOT. +#if __ISO_C_VISIBLE >= 2011 +# if defined(__FreeBSD__) +# define TEST_HAS_C11_FEATURES +# elif defined(__Fuchsia__) +# define TEST_HAS_C11_FEATURES +# elif defined(__linux__) +# if !defined(_LIBCPP_HAS_MUSL_LIBC) +# if _LIBCPP_GLIBC_PREREQ(2, 17) +# define TEST_HAS_C11_FEATURES +# endif +# else // defined(_LIBCPP_HAS_MUSL_LIBC) +# define TEST_HAS_C11_FEATURES +# endif +# elif defined(_WIN32) +# if defined(_MSC_VER) && !defined(__MINGW32__) +# define TEST_HAS_C11_FEATURES // Using Microsoft's C Runtime library +# endif +# endif +#endif + +/* Features that were introduced in C++14 */ +#if TEST_STD_VER >= 14 +#define TEST_HAS_EXTENDED_CONSTEXPR +#define TEST_HAS_VARIABLE_TEMPLATES +#endif + +/* Features that were introduced in C++17 */ +#if TEST_STD_VER >= 17 +#endif + +/* Features that were introduced after C++17 */ +#if TEST_STD_VER > 17 +#endif + + #define TEST_ALIGNAS_TYPE(...) TEST_ALIGNAS(TEST_ALIGNOF(__VA_ARGS__)) #if !TEST_HAS_FEATURE(cxx_rtti) && !defined(__cpp_rtti) \ -- GitLab From 8a16d409915006fbf9d6f0828cfcf4015fadca06 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 31 Jul 2018 19:25:00 +0000 Subject: [PATCH 114/495] import timespec and timespec_get into namespace std if we're under c++17 or later AND the underlying C library has them. Fixes PR#38220, but doesn't implement all of P0063 yet. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338419 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/ctime | 14 +++++++++++--- .../support.runtime/ctime.pass.cpp | 14 ++++++++++++++ test/std/utilities/time/date.time/ctime.pass.cpp | 16 ++++++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/include/ctime b/include/ctime index da9e3290b..81cf11a46 100644 --- a/include/ctime +++ b/include/ctime @@ -18,7 +18,8 @@ Macros: NULL CLOCKS_PER_SEC - + TIME_UTC // C++17 + namespace std { @@ -28,7 +29,8 @@ Types: size_t time_t tm - + timespec // C++17 + clock_t clock(); double difftime(time_t time1, time_t time0); time_t mktime(tm* timeptr); @@ -39,7 +41,7 @@ tm* gmtime(const time_t* timer); tm* localtime(const time_t* timer); size_t strftime(char* restrict s, size_t maxsize, const char* restrict format, const tm* restrict timeptr); - +int timespec_get( struct timespec *ts, int base); // C++17 } // std */ @@ -57,6 +59,9 @@ using ::clock_t; using ::size_t; using ::time_t; using ::tm; +#if _LIBCPP_STD_VER > 14 && defined(_LIBCPP_HAS_C11_FEATURES) +using ::timespec; +#endif using ::clock; using ::difftime; using ::mktime; @@ -68,6 +73,9 @@ using ::gmtime; using ::localtime; #endif using ::strftime; +#if _LIBCPP_STD_VER > 14 && defined(_LIBCPP_HAS_C11_FEATURES) +using ::timespec_get; +#endif _LIBCPP_END_NAMESPACE_STD diff --git a/test/std/language.support/support.runtime/ctime.pass.cpp b/test/std/language.support/support.runtime/ctime.pass.cpp index 34343b247..908dc4808 100644 --- a/test/std/language.support/support.runtime/ctime.pass.cpp +++ b/test/std/language.support/support.runtime/ctime.pass.cpp @@ -11,6 +11,7 @@ #include #include +#include "test_macros.h" #ifndef NULL #error NULL not defined @@ -20,12 +21,22 @@ #error CLOCKS_PER_SEC not defined #endif +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) +#ifndef TIME_UTC +#error TIME_UTC not defined +#endif +#endif + int main() { std::clock_t c = 0; std::size_t s = 0; std::time_t t = 0; std::tm tm = {}; +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) + std::timespec tmspec = {}; + ((void)tmspec); // Prevent unused warning +#endif ((void)c); // Prevent unused warning ((void)s); // Prevent unused warning ((void)t); // Prevent unused warning @@ -34,6 +45,9 @@ int main() static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) + static_assert((std::is_same::value), ""); +#endif #ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); diff --git a/test/std/utilities/time/date.time/ctime.pass.cpp b/test/std/utilities/time/date.time/ctime.pass.cpp index b9e19af32..fe9f38daa 100644 --- a/test/std/utilities/time/date.time/ctime.pass.cpp +++ b/test/std/utilities/time/date.time/ctime.pass.cpp @@ -10,6 +10,8 @@ #include #include +#include "test_macros.h" + #ifndef NULL #error NULL not defined #endif @@ -18,6 +20,12 @@ #error CLOCKS_PER_SEC not defined #endif +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) +#ifndef TIME_UTC +#error TIME_UTC not defined +#endif +#endif + int main() { std::clock_t c = 0; @@ -30,10 +38,18 @@ int main() ((void)t); // Prevent unused warning ((void)tm); // Prevent unused warning ((void)str); // Prevent unused warning +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) + std::timespec tmspec = {}; + ((void)tmspec); // Prevent unused warning +#endif + static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) + static_assert((std::is_same::value), ""); +#endif #ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); -- GitLab From 4983a7a649d1cccc8f648d1a7fbbed6990720449 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 31 Jul 2018 23:29:06 +0000 Subject: [PATCH 115/495] Test for the presence of a bunch of new macros for c++17. These macros come from C11. Part of P0063 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338454 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/cfloat | 10 +++++ include/float.h | 11 +++++ test/std/depr/depr.c.headers/float_h.pass.cpp | 42 +++++++++++++++++++ .../support.limits/c.limits/cfloat.pass.cpp | 42 +++++++++++++++++++ 4 files changed, 105 insertions(+) diff --git a/include/cfloat b/include/cfloat index 176fa9de3..0abe84bf1 100644 --- a/include/cfloat +++ b/include/cfloat @@ -20,11 +20,18 @@ Macros: FLT_EVAL_METHOD // C99 FLT_RADIX + FLT_HAS_SUBNORM // C11 + DBL_HAS_SUBNORM // C11 + LDBL_HAS_SUBNORM // C11 + FLT_MANT_DIG DBL_MANT_DIG LDBL_MANT_DIG DECIMAL_DIG // C99 + FLT_DECIMAL_DIG // C11 + DBL_DECIMAL_DIG // C11 + LDBL_DECIMAL_DIG // C11 FLT_DIG DBL_DIG @@ -58,6 +65,9 @@ Macros: DBL_MIN LDBL_MIN + FLT_TRUE_MIN // C11 + DBL_TRUE_MIN // C11 + LDBL_TRUE_MIN // C11 */ #include <__config> diff --git a/include/float.h b/include/float.h index 1acfdc618..759ac8e79 100644 --- a/include/float.h +++ b/include/float.h @@ -24,7 +24,14 @@ Macros: DBL_MANT_DIG LDBL_MANT_DIG + FLT_HAS_SUBNORM // C11 + DBL_HAS_SUBNORM // C11 + LDBL_HAS_SUBNORM // C11 + DECIMAL_DIG // C99 + FLT_DECIMAL_DIG // C11 + DBL_DECIMAL_DIG // C11 + LDBL_DECIMAL_DIG // C11 FLT_DIG DBL_DIG @@ -58,6 +65,10 @@ Macros: DBL_MIN LDBL_MIN + FLT_TRUE_MIN // C11 + DBL_TRUE_MIN // C11 + LDBL_TRUE_MIN // C11 + */ #include <__config> diff --git a/test/std/depr/depr.c.headers/float_h.pass.cpp b/test/std/depr/depr.c.headers/float_h.pass.cpp index 5b2e45163..3001c215c 100644 --- a/test/std/depr/depr.c.headers/float_h.pass.cpp +++ b/test/std/depr/depr.c.headers/float_h.pass.cpp @@ -23,6 +23,20 @@ #error FLT_RADIX not defined #endif +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) +#ifndef FLT_HAS_SUBNORM +#error FLT_HAS_SUBNORM not defined +#endif + +#ifndef DBL_HAS_SUBNORM +#error DBL_HAS_SUBNORM not defined +#endif + +#ifndef LDBL_HAS_SUBNORM +#error LDBL_HAS_SUBNORM not defined +#endif +#endif + #ifndef FLT_MANT_DIG #error FLT_MANT_DIG not defined #endif @@ -39,6 +53,20 @@ #error DECIMAL_DIG not defined #endif +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) +#ifndef FLT_DECIMAL_DIG +#error FLT_DECIMAL_DIG not defined +#endif + +#ifndef DBL_DECIMAL_DIG +#error DBL_DECIMAL_DIG not defined +#endif + +#ifndef LDBL_DECIMAL_DIG +#error LDBL_DECIMAL_DIG not defined +#endif +#endif + #ifndef FLT_DIG #error FLT_DIG not defined #endif @@ -135,6 +163,20 @@ #error LDBL_MIN not defined #endif +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) +#ifndef FLT_TRUE_MIN +#error FLT_TRUE_MIN not defined +#endif + +#ifndef DBL_TRUE_MIN +#error DBL_TRUE_MIN not defined +#endif + +#ifndef LDBL_TRUE_MIN +#error LDBL_TRUE_MIN not defined +#endif +#endif + int main() { } diff --git a/test/std/language.support/support.limits/c.limits/cfloat.pass.cpp b/test/std/language.support/support.limits/c.limits/cfloat.pass.cpp index 5f63af68f..6e399d093 100644 --- a/test/std/language.support/support.limits/c.limits/cfloat.pass.cpp +++ b/test/std/language.support/support.limits/c.limits/cfloat.pass.cpp @@ -23,6 +23,20 @@ #error FLT_RADIX not defined #endif +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) +#ifndef FLT_HAS_SUBNORM +#error FLT_HAS_SUBNORM not defined +#endif + +#ifndef DBL_HAS_SUBNORM +#error DBL_HAS_SUBNORM not defined +#endif + +#ifndef LDBL_HAS_SUBNORM +#error LDBL_HAS_SUBNORM not defined +#endif +#endif + #ifndef FLT_MANT_DIG #error FLT_MANT_DIG not defined #endif @@ -39,6 +53,20 @@ #error DECIMAL_DIG not defined #endif +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) +#ifndef FLT_DECIMAL_DIG +#error FLT_DECIMAL_DIG not defined +#endif + +#ifndef DBL_DECIMAL_DIG +#error DBL_DECIMAL_DIG not defined +#endif + +#ifndef LDBL_DECIMAL_DIG +#error LDBL_DECIMAL_DIG not defined +#endif +#endif + #ifndef FLT_DIG #error FLT_DIG not defined #endif @@ -135,6 +163,20 @@ #error LDBL_MIN not defined #endif +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) +#ifndef FLT_TRUE_MIN +#error FLT_TRUE_MIN not defined +#endif + +#ifndef DBL_TRUE_MIN +#error DBL_TRUE_MIN not defined +#endif + +#ifndef LDBL_TRUE_MIN +#error LDBL_TRUE_MIN not defined +#endif +#endif + int main() { } -- GitLab From ea96e3a7070886c8f6132d354fc0607ff3d43a54 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Tue, 31 Jul 2018 23:39:12 +0000 Subject: [PATCH 116/495] Final bit of P0063 - make sure that aligned_alloc is available when the underlying C library supports it git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338457 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/std/depr/depr.c.headers/stdlib_h.pass.cpp | 10 ++++++++++ .../language.support/support.runtime/cstdlib.pass.cpp | 10 ++++++++++ www/cxx1z_status.html | 8 ++++---- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/test/std/depr/depr.c.headers/stdlib_h.pass.cpp b/test/std/depr/depr.c.headers/stdlib_h.pass.cpp index 1680f4349..07ffa0b75 100644 --- a/test/std/depr/depr.c.headers/stdlib_h.pass.cpp +++ b/test/std/depr/depr.c.headers/stdlib_h.pass.cpp @@ -12,6 +12,8 @@ #include #include +#include "test_macros.h" + // As of 1/10/2015 clang emits a -Wnonnull warnings even if the warning occurs // in an unevaluated context. For this reason we manually suppress the warning. #if defined(__clang__) @@ -83,6 +85,14 @@ int main() static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); + +// Microsoft does not implement aligned_alloc in their C library +#ifndef TEST_COMPILER_C1XX +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) + static_assert((std::is_same::value), ""); +#endif +#endif + static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); diff --git a/test/std/language.support/support.runtime/cstdlib.pass.cpp b/test/std/language.support/support.runtime/cstdlib.pass.cpp index 60f7d954d..e9dda6cee 100644 --- a/test/std/language.support/support.runtime/cstdlib.pass.cpp +++ b/test/std/language.support/support.runtime/cstdlib.pass.cpp @@ -13,6 +13,8 @@ #include #include +#include "test_macros.h" + // As of 1/10/2015 clang emits a -Wnonnull warnings even if the warning occurs // in an unevaluated context. For this reason we manually suppress the warning. #if defined(__clang__) @@ -71,6 +73,14 @@ int main() static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); + +// Microsoft does not implement aligned_alloc in their C library +#ifndef TEST_COMPILER_C1XX +#if TEST_STD_VER > 14 && defined(TEST_HAS_C11_FEATURES) + static_assert((std::is_same::value), ""); +#endif +#endif + static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); diff --git a/www/cxx1z_status.html b/www/cxx1z_status.html index dc3528373..5f713ede9 100644 --- a/www/cxx1z_status.html +++ b/www/cxx1z_status.html @@ -99,9 +99,9 @@ p0032r3LWGHomogeneous interface for variant, any and optionalOuluComplete4.0 p0040r3LWGExtending memory management toolsOuluComplete4.0 - p0063r3LWGC++17 should refer to C11 instead of C99OuluNothing to don/a - p0067r3LWGElementary string conversionsOuluNow P0067R5 - p0083r3LWGSplicing Maps and SetsOulu + p0063r3LWGC++17 should refer to C11 instead of C99OuluComplete7.0 + p0067r3LWGElementary string conversionsOuluNow P0067R5n/a + p0083r3LWGSplicing Maps and SetsOuluPartially Done p0084r2LWGEmplace Return TypeOuluComplete4.0 p0088r3LWGVariant: a type-safe union for C++17OuluComplete4.0 p0137r1CWGCore Issue 1776: Replacement of class objects containing reference membersOuluComplete6.0 @@ -127,7 +127,7 @@ P0394r4LWGHotel Parallelifornia: terminate() for Parallel Algorithms Exception HandlingOulu P0003R5LWGRemoving Deprecated Exception Specifications from C++17IssaquahComplete5.0 - P0067R5LWGElementary string conversions, revision 5Issaquah + P0067R5LWGElementary string conversions, revision 5IssaquahPartially done P0403R1LWGLiteral suffixes for basic_string_viewIssaquahComplete4.0 P0414R2LWGMerging shared_ptr changes from Library Fundamentals to C++17Issaquah P0418R2LWGFail or succeed: there is no atomic latticeIssaquah -- GitLab From 36fc7371891fd73ba9a86dd4e62421866ecc5901 Mon Sep 17 00:00:00 2001 From: Erik Pilkington Date: Wed, 1 Aug 2018 01:33:38 +0000 Subject: [PATCH 117/495] First half of C++17's splicing maps and sets This commit adds a node handle type, (located in __node_handle), and adds extract() and insert() members to all map and set types, as well as their implementations in __tree and __hash_table. The second half of this feature is adding merge() members, which splice nodes in bulk from one container into another. This will be committed in a follow-up. Differential revision: https://reviews.llvm.org/D46845 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338472 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/CMakeLists.txt | 1 + include/__hash_table | 120 ++++++++++ include/__node_handle | 212 ++++++++++++++++++ include/__tree | 170 +++++++++++++- include/map | 83 +++++++ include/module.modulemap | 1 + include/set | 81 +++++++ include/unordered_map | 87 ++++++- include/unordered_set | 84 +++++++ .../map.modifiers/extract_iterator.pass.cpp | 67 ++++++ .../map/map.modifiers/extract_key.pass.cpp | 76 +++++++ .../map.modifiers/insert_node_type.pass.cpp | 85 +++++++ .../insert_node_type_hint.pass.cpp | 64 ++++++ .../extract_iterator.pass.cpp | 67 ++++++ .../multimap.modifiers/extract_key.pass.cpp | 76 +++++++ .../insert_node_type.pass.cpp | 78 +++++++ .../insert_node_type_hint.pass.cpp | 64 ++++++ .../multiset/extract_iterator.pass.cpp | 60 +++++ .../associative/multiset/extract_key.pass.cpp | 71 ++++++ .../multiset/insert_node_type.pass.cpp | 77 +++++++ .../multiset/insert_node_type_hint.pass.cpp | 59 +++++ .../associative/set/extract_iterator.pass.cpp | 60 +++++ .../associative/set/extract_key.pass.cpp | 71 ++++++ .../associative/set/insert_node_type.pass.cpp | 83 +++++++ .../set/insert_node_type_hint.pass.cpp | 61 +++++ .../container.node/node_handle.pass.cpp | 145 ++++++++++++ .../extract_iterator.pass.cpp | 67 ++++++ .../unord.map.modifiers/extract_key.pass.cpp | 76 +++++++ .../insert_node_type.pass.cpp | 84 +++++++ .../insert_node_type_hint.pass.cpp | 64 ++++++ .../extract_iterator.pass.cpp | 67 ++++++ .../extract_key.pass.cpp | 77 +++++++ .../insert_node_type.pass.cpp | 77 +++++++ .../insert_node_type_hint.pass.cpp | 63 ++++++ .../unord.multiset/extract_iterator.pass.cpp | 60 +++++ .../unord/unord.multiset/extract_key.pass.cpp | 71 ++++++ .../unord.multiset/insert_node_type.pass.cpp | 76 +++++++ .../insert_node_type_hint.pass.cpp | 59 +++++ .../unord/unord.set/extract_iterator.pass.cpp | 60 +++++ .../unord/unord.set/extract_key.pass.cpp | 71 ++++++ .../unord/unord.set/insert_node_type.pass.cpp | 83 +++++++ .../unord.set/insert_node_type_hint.pass.cpp | 61 +++++ test/support/Counter.h | 4 +- 43 files changed, 3214 insertions(+), 9 deletions(-) create mode 100644 include/__node_handle create mode 100644 test/std/containers/associative/map/map.modifiers/extract_iterator.pass.cpp create mode 100644 test/std/containers/associative/map/map.modifiers/extract_key.pass.cpp create mode 100644 test/std/containers/associative/map/map.modifiers/insert_node_type.pass.cpp create mode 100644 test/std/containers/associative/map/map.modifiers/insert_node_type_hint.pass.cpp create mode 100644 test/std/containers/associative/multimap/multimap.modifiers/extract_iterator.pass.cpp create mode 100644 test/std/containers/associative/multimap/multimap.modifiers/extract_key.pass.cpp create mode 100644 test/std/containers/associative/multimap/multimap.modifiers/insert_node_type.pass.cpp create mode 100644 test/std/containers/associative/multimap/multimap.modifiers/insert_node_type_hint.pass.cpp create mode 100644 test/std/containers/associative/multiset/extract_iterator.pass.cpp create mode 100644 test/std/containers/associative/multiset/extract_key.pass.cpp create mode 100644 test/std/containers/associative/multiset/insert_node_type.pass.cpp create mode 100644 test/std/containers/associative/multiset/insert_node_type_hint.pass.cpp create mode 100644 test/std/containers/associative/set/extract_iterator.pass.cpp create mode 100644 test/std/containers/associative/set/extract_key.pass.cpp create mode 100644 test/std/containers/associative/set/insert_node_type.pass.cpp create mode 100644 test/std/containers/associative/set/insert_node_type_hint.pass.cpp create mode 100644 test/std/containers/container.node/node_handle.pass.cpp create mode 100644 test/std/containers/unord/unord.map/unord.map.modifiers/extract_iterator.pass.cpp create mode 100644 test/std/containers/unord/unord.map/unord.map.modifiers/extract_key.pass.cpp create mode 100644 test/std/containers/unord/unord.map/unord.map.modifiers/insert_node_type.pass.cpp create mode 100644 test/std/containers/unord/unord.map/unord.map.modifiers/insert_node_type_hint.pass.cpp create mode 100644 test/std/containers/unord/unord.multimap/unord.multimap.modifiers/extract_iterator.pass.cpp create mode 100644 test/std/containers/unord/unord.multimap/unord.multimap.modifiers/extract_key.pass.cpp create mode 100644 test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_node_type.pass.cpp create mode 100644 test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_node_type_hint.pass.cpp create mode 100644 test/std/containers/unord/unord.multiset/extract_iterator.pass.cpp create mode 100644 test/std/containers/unord/unord.multiset/extract_key.pass.cpp create mode 100644 test/std/containers/unord/unord.multiset/insert_node_type.pass.cpp create mode 100644 test/std/containers/unord/unord.multiset/insert_node_type_hint.pass.cpp create mode 100644 test/std/containers/unord/unord.set/extract_iterator.pass.cpp create mode 100644 test/std/containers/unord/unord.set/extract_key.pass.cpp create mode 100644 test/std/containers/unord/unord.set/insert_node_type.pass.cpp create mode 100644 test/std/containers/unord/unord.set/insert_node_type_hint.pass.cpp diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index c5e92e4c4..a45b80160 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -11,6 +11,7 @@ set(files __libcpp_version __locale __mutex_base + __node_handle __nullptr __split_buffer __sso_allocator diff --git a/include/__hash_table b/include/__hash_table index 44ba268a0..c77de961b 100644 --- a/include/__hash_table +++ b/include/__hash_table @@ -859,6 +859,17 @@ public: template friend class __hash_map_node_destructor; }; +#if _LIBCPP_STD_VER > 14 +template +struct __generic_container_node_destructor; + +template +struct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc> + : __hash_node_destructor<_Alloc> +{ + using __hash_node_destructor<_Alloc>::__hash_node_destructor; +}; +#endif #ifndef _LIBCPP_CXX03_LANG template @@ -1151,6 +1162,30 @@ public: return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x); } +#if _LIBCPP_STD_VER > 14 + template + _LIBCPP_INLINE_VISIBILITY + _InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh); + template + _LIBCPP_INLINE_VISIBILITY + iterator __node_handle_insert_unique(const_iterator __hint, + _NodeHandle&& __nh); + + template + _LIBCPP_INLINE_VISIBILITY + iterator __node_handle_insert_multi(_NodeHandle&& __nh); + template + _LIBCPP_INLINE_VISIBILITY + iterator __node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh); + + template + _LIBCPP_INLINE_VISIBILITY + _NodeHandle __node_handle_extract(key_type const& __key); + template + _LIBCPP_INLINE_VISIBILITY + _NodeHandle __node_handle_extract(const_iterator __it); +#endif + void clear() _NOEXCEPT; void rehash(size_type __n); _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) @@ -2126,6 +2161,91 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p, #endif // _LIBCPP_CXX03_LANG +#if _LIBCPP_STD_VER > 14 +template +template +_LIBCPP_INLINE_VISIBILITY +_InsertReturnType +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique( + _NodeHandle&& __nh) +{ + if (__nh.empty()) + return _InsertReturnType{end(), false, _NodeHandle()}; + pair __result = __node_insert_unique(__nh.__ptr_); + if (__result.second) + __nh.__release(); + return _InsertReturnType{__result.first, __result.second, _VSTD::move(__nh)}; +} + +template +template +_LIBCPP_INLINE_VISIBILITY +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique( + const_iterator, _NodeHandle&& __nh) +{ + if (__nh.empty()) + return end(); + pair __result = __node_insert_unique(__nh.__ptr_); + if (__result.second) + __nh.__release(); + return __result.first; +} + +template +template +_LIBCPP_INLINE_VISIBILITY +_NodeHandle +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract( + key_type const& __key) +{ + iterator __i = find(__key); + if (__i == end()) + return _NodeHandle(); + return __node_handle_extract<_NodeHandle>(__i); +} + +template +template +_LIBCPP_INLINE_VISIBILITY +_NodeHandle +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract( + const_iterator __p) +{ + allocator_type __alloc(__node_alloc()); + return _NodeHandle(remove(__p).release(), __alloc); +} + +template +template +_LIBCPP_INLINE_VISIBILITY +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi( + _NodeHandle&& __nh) +{ + if (__nh.empty()) + return end(); + iterator __result = __node_insert_multi(__nh.__ptr_); + __nh.__release(); + return __result; +} + +template +template +_LIBCPP_INLINE_VISIBILITY +typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator +__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi( + const_iterator __hint, _NodeHandle&& __nh) +{ + if (__nh.empty()) + return end(); + iterator __result = __node_insert_multi(__hint, __nh.__ptr_); + __nh.__release(); + return __result; +} + +#endif // _LIBCPP_STD_VER > 14 + template void __hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n) diff --git a/include/__node_handle b/include/__node_handle new file mode 100644 index 000000000..fe09f3c1e --- /dev/null +++ b/include/__node_handle @@ -0,0 +1,212 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___NODE_HANDLE +#define _LIBCPP___NODE_HANDLE + +#include <__config> +#include +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 14 + +#define __cpp_lib_node_extract 201606L + +// Specialized in __tree & __hash_table for their _NodeType. +template +struct __generic_container_node_destructor; + +template class _MapOrSetSpecifics> +class _LIBCPP_TEMPLATE_VIS __basic_node_handle + : public _MapOrSetSpecifics< + _NodeType, + __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>> +{ + template + friend class __tree; + template + friend class __hash_table; + friend struct _MapOrSetSpecifics< + _NodeType, __basic_node_handle<_NodeType, _Alloc, _MapOrSetSpecifics>>; + + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_pointer::type + __node_pointer_type; + +public: + typedef _Alloc allocator_type; + +private: + __node_pointer_type __ptr_ = nullptr; + optional __alloc_; + + _LIBCPP_INLINE_VISIBILITY + void __release() + { + __ptr_ = nullptr; + __alloc_ = _VSTD::nullopt; + } + + _LIBCPP_INLINE_VISIBILITY + void __destroy_node_pointer() + { + if (__ptr_ != nullptr) + { + typedef typename __allocator_traits_rebind< + allocator_type, _NodeType>::type __node_alloc_type; + __node_alloc_type __alloc(*__alloc_); + __generic_container_node_destructor<_NodeType, __node_alloc_type>( + __alloc, true)(__ptr_); + __ptr_ = nullptr; + } + } + + _LIBCPP_INLINE_VISIBILITY + __basic_node_handle(__node_pointer_type __ptr, + allocator_type const& __alloc) + : __ptr_(__ptr), __alloc_(__alloc) + { + } + +public: + _LIBCPP_INLINE_VISIBILITY + __basic_node_handle() = default; + + _LIBCPP_INLINE_VISIBILITY + __basic_node_handle(__basic_node_handle&& __other) noexcept + : __ptr_(__other.__ptr_), + __alloc_(_VSTD::move(__other.__alloc_)) + { + __other.__ptr_ = nullptr; + __other.__alloc_ = _VSTD::nullopt; + } + + _LIBCPP_INLINE_VISIBILITY + __basic_node_handle& operator=(__basic_node_handle&& __other) + { + _LIBCPP_ASSERT( + __alloc_ == _VSTD::nullopt || + __alloc_traits::propagate_on_container_move_assignment::value || + __alloc_ == __other.__alloc_, + "node_type with incompatible allocator passed to " + "node_type::operator=(node_type&&)"); + + __destroy_node_pointer(); + __ptr_ = __other.__ptr_; + + if (__alloc_traits::propagate_on_container_move_assignment::value || + __alloc_ == _VSTD::nullopt) + __alloc_ = _VSTD::move(__other.__alloc_); + + __other.__ptr_ = nullptr; + __other.__alloc_ = _VSTD::nullopt; + + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + allocator_type get_allocator() const { return *__alloc_; } + + _LIBCPP_INLINE_VISIBILITY + explicit operator bool() const { return __ptr_ != nullptr; } + + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY + bool empty() const { return __ptr_ == nullptr; } + + _LIBCPP_INLINE_VISIBILITY + void swap(__basic_node_handle& __other) noexcept( + __alloc_traits::propagate_on_container_swap::value || + __alloc_traits::is_always_equal::value) + { + using _VSTD::swap; + swap(__ptr_, __other.__ptr_); + if (__alloc_traits::propagate_on_container_swap::value || + __alloc_ == _VSTD::nullopt || __other.__alloc_ == _VSTD::nullopt) + swap(__alloc_, __other.__alloc_); + } + + _LIBCPP_INLINE_VISIBILITY + friend void swap(__basic_node_handle& __a, __basic_node_handle& __b) + noexcept(noexcept(__a.swap(__b))) { __a.swap(__b); } + + _LIBCPP_INLINE_VISIBILITY + ~__basic_node_handle() + { + __destroy_node_pointer(); + } +}; + +template +struct __set_node_handle_specifics +{ + typedef typename _NodeType::__node_value_type value_type; + + _LIBCPP_INLINE_VISIBILITY + value_type& value() const + { + return static_cast<_Derived const*>(this)->__ptr_->__value_; + } +}; + +template +struct __map_node_handle_specifics +{ + typedef typename _NodeType::__node_value_type::key_type key_type; + typedef typename _NodeType::__node_value_type::mapped_type mapped_type; + + _LIBCPP_INLINE_VISIBILITY + key_type& key() const + { + return static_cast<_Derived const*>(this)-> + __ptr_->__value_.__ref().first; + } + + _LIBCPP_INLINE_VISIBILITY + mapped_type& mapped() const + { + return static_cast<_Derived const*>(this)-> + __ptr_->__value_.__ref().second; + } +}; + +template +using __set_node_handle = + __basic_node_handle< _NodeType, _Alloc, __set_node_handle_specifics>; + +template +using __map_node_handle = + __basic_node_handle< _NodeType, _Alloc, __map_node_handle_specifics>; + +template +_LIBCPP_TEMPLATE_VIS +struct __insert_return_type +{ + _Iterator position; + bool inserted; + _NodeType node; +}; + +#endif // _LIBCPP_STD_VER > 14 + +_LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + +#endif diff --git a/include/__tree b/include/__tree index 30c32f163..af9b9616d 100644 --- a/include/__tree +++ b/include/__tree @@ -796,6 +796,16 @@ public: template friend class __map_node_destructor; }; +#if _LIBCPP_STD_VER > 14 +template +struct __generic_container_node_destructor; +template +struct __generic_container_node_destructor<__tree_node<_Tp, _VoidPtr>, _Alloc> + : __tree_node_destructor<_Alloc> +{ + using __tree_node_destructor<_Alloc>::__tree_node_destructor; +}; +#endif template class _LIBCPP_TEMPLATE_VIS __tree_iterator @@ -1338,6 +1348,33 @@ public: iterator __node_insert_multi(__node_pointer __nd); iterator __node_insert_multi(const_iterator __p, __node_pointer __nd); + + _LIBCPP_INLINE_VISIBILITY iterator __remove_node_pointer(__node_pointer); + +#if _LIBCPP_STD_VER > 14 + template + _LIBCPP_INLINE_VISIBILITY + _InsertReturnType __node_handle_insert_unique(_NodeHandle&&); + template + _LIBCPP_INLINE_VISIBILITY + iterator __node_handle_insert_unique(const_iterator, _NodeHandle&&); + + template + _LIBCPP_INLINE_VISIBILITY + iterator __node_handle_insert_multi(_NodeHandle&&); + template + _LIBCPP_INLINE_VISIBILITY + iterator __node_handle_insert_multi(const_iterator, _NodeHandle&&); + + + template + _LIBCPP_INLINE_VISIBILITY + _NodeHandle __node_handle_extract(key_type const&); + template + _LIBCPP_INLINE_VISIBILITY + _NodeHandle __node_handle_extract(const_iterator); +#endif + iterator erase(const_iterator __p); iterator erase(const_iterator __f, const_iterator __l); template @@ -2347,17 +2384,138 @@ __tree<_Tp, _Compare, _Allocator>::__node_insert_multi(const_iterator __p, template typename __tree<_Tp, _Compare, _Allocator>::iterator -__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p) +__tree<_Tp, _Compare, _Allocator>::__remove_node_pointer(__node_pointer __ptr) { - __node_pointer __np = __p.__get_np(); - iterator __r(__p.__ptr_); + iterator __r(__ptr); ++__r; - if (__begin_node() == __p.__ptr_) + if (__begin_node() == __ptr) __begin_node() = __r.__ptr_; --size(); - __node_allocator& __na = __node_alloc(); __tree_remove(__end_node()->__left_, - static_cast<__node_base_pointer>(__np)); + static_cast<__node_base_pointer>(__ptr)); + return __r; +} + +#if _LIBCPP_STD_VER > 14 +template +template +_LIBCPP_INLINE_VISIBILITY +_InsertReturnType +__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique( + _NodeHandle&& __nh) +{ + if (__nh.empty()) + return _InsertReturnType{end(), false, _NodeHandle()}; + + __node_pointer __ptr = __nh.__ptr_; + __parent_pointer __parent; + __node_base_pointer& __child = __find_equal(__parent, + __ptr->__value_); + if (__child != nullptr) + return _InsertReturnType{ + iterator(static_cast<__node_pointer>(__child)), + false, _VSTD::move(__nh)}; + + __insert_node_at(__parent, __child, + static_cast<__node_base_pointer>(__ptr)); + __nh.__release(); + return _InsertReturnType{iterator(__ptr), true, _NodeHandle()}; +} + +template +template +_LIBCPP_INLINE_VISIBILITY +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_unique( + const_iterator __hint, _NodeHandle&& __nh) +{ + if (__nh.empty()) + return end(); + + __node_pointer __ptr = __nh.__ptr_; + __parent_pointer __parent; + __node_base_pointer __dummy; + __node_base_pointer& __child = __find_equal(__hint, __parent, __dummy, + __ptr->__value_); + __node_pointer __r = static_cast<__node_pointer>(__child); + if (__child == nullptr) + { + __insert_node_at(__parent, __child, + static_cast<__node_base_pointer>(__ptr)); + __r = __ptr; + __nh.__release(); + } + return iterator(__r); +} + +template +template +_LIBCPP_INLINE_VISIBILITY +_NodeHandle +__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(key_type const& __key) +{ + iterator __it = find(__key); + if (__it == end()) + return _NodeHandle(); + return __node_handle_extract<_NodeHandle>(__it); +} + +template +template +_LIBCPP_INLINE_VISIBILITY +_NodeHandle +__tree<_Tp, _Compare, _Allocator>::__node_handle_extract(const_iterator __p) +{ + __node_pointer __np = __p.__get_np(); + __remove_node_pointer(__np); + return _NodeHandle(__np, __alloc()); +} + +template +template +_LIBCPP_INLINE_VISIBILITY +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi(_NodeHandle&& __nh) +{ + if (__nh.empty()) + return end(); + __node_pointer __ptr = __nh.__ptr_; + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf_high( + __parent, _NodeTypes::__get_key(__ptr->__value_)); + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr)); + __nh.__release(); + return iterator(__ptr); +} + +template +template +_LIBCPP_INLINE_VISIBILITY +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::__node_handle_insert_multi( + const_iterator __hint, _NodeHandle&& __nh) +{ + if (__nh.empty()) + return end(); + + __node_pointer __ptr = __nh.__ptr_; + __parent_pointer __parent; + __node_base_pointer& __child = __find_leaf(__hint, __parent, + _NodeTypes::__get_key(__ptr->__value_)); + __insert_node_at(__parent, __child, static_cast<__node_base_pointer>(__ptr)); + __nh.__release(); + return iterator(__ptr); +} + +#endif // _LIBCPP_STD_VER > 14 + +template +typename __tree<_Tp, _Compare, _Allocator>::iterator +__tree<_Tp, _Compare, _Allocator>::erase(const_iterator __p) +{ + __node_pointer __np = __p.__get_np(); + iterator __r = __remove_node_pointer(__np); + __node_allocator& __na = __node_alloc(); __node_traits::destroy(__na, _NodeTypes::__get_ptr( const_cast<__node_value_type&>(*__p))); __node_traits::deallocate(__na, __np, 1); diff --git a/include/map b/include/map index 97ce4d0b1..559ec484a 100644 --- a/include/map +++ b/include/map @@ -40,6 +40,8 @@ public: typedef implementation-defined const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; + typedef unspecified node_type; // C++17 + typedef INSERT_RETURN_TYPE insert_return_type; // C++17 class value_compare : public binary_function @@ -137,6 +139,11 @@ public: void insert(InputIterator first, InputIterator last); void insert(initializer_list il); + node_type extract(const_iterator position); // C++17 + node_type extract(const key_type& x); // C++17 + insert_return_type insert(node_type&& nh); // C++17 + iterator insert(const_iterator hint, node_type&& nh); // C++17 + template pair try_emplace(const key_type& k, Args&&... args); // C++17 template @@ -260,6 +267,7 @@ public: typedef implementation-defined const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; + typedef unspecified node_type; // C++17 class value_compare : public binary_function @@ -349,6 +357,11 @@ public: void insert(InputIterator first, InputIterator last); void insert(initializer_list il); + node_type extract(const_iterator position); // C++17 + node_type extract(const key_type& x); // C++17 + iterator insert(node_type&& nh); // C++17 + iterator insert(const_iterator hint, node_type&& nh); // C++17 + iterator erase(const_iterator position); iterator erase(iterator position); // C++14 size_type erase(const key_type& k); @@ -440,6 +453,7 @@ swap(multimap& x, #include <__config> #include <__tree> +#include <__node_handle> #include #include #include @@ -906,6 +920,11 @@ public: typedef _VSTD::reverse_iterator reverse_iterator; typedef _VSTD::reverse_iterator const_reverse_iterator; +#if _LIBCPP_STD_VER > 14 + typedef __map_node_handle node_type; + typedef __insert_return_type insert_return_type; +#endif + _LIBCPP_INLINE_VISIBILITY map() _NOEXCEPT_( @@ -1253,6 +1272,35 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__tree_.clear();} +#if _LIBCPP_STD_VER > 14 + _LIBCPP_INLINE_VISIBILITY + insert_return_type insert(node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to map::insert()"); + return __tree_.template __node_handle_insert_unique< + node_type, insert_return_type>(_VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + iterator insert(const_iterator __hint, node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to map::insert()"); + return __tree_.template __node_handle_insert_unique( + __hint.__i_, _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(key_type const& __key) + { + return __tree_.template __node_handle_extract(__key); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(const_iterator __it) + { + return __tree_.template __node_handle_extract(__it.__i_); + } +#endif + _LIBCPP_INLINE_VISIBILITY void swap(map& __m) _NOEXCEPT_(__is_nothrow_swappable<__base>::value) @@ -1562,6 +1610,10 @@ public: typedef _VSTD::reverse_iterator reverse_iterator; typedef _VSTD::reverse_iterator const_reverse_iterator; +#if _LIBCPP_STD_VER > 14 + typedef __map_node_handle node_type; +#endif + _LIBCPP_INLINE_VISIBILITY multimap() _NOEXCEPT_( @@ -1800,6 +1852,37 @@ public: _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __f, const_iterator __l) {return __tree_.erase(__f.__i_, __l.__i_);} + +#if _LIBCPP_STD_VER > 14 + _LIBCPP_INLINE_VISIBILITY + iterator insert(node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to multimap::insert()"); + return __tree_.template __node_handle_insert_multi( + _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + iterator insert(const_iterator __hint, node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to multimap::insert()"); + return __tree_.template __node_handle_insert_multi( + __hint.__i_, _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(key_type const& __key) + { + return __tree_.template __node_handle_extract(__key); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(const_iterator __it) + { + return __tree_.template __node_handle_extract( + __it.__i_); + } +#endif + _LIBCPP_INLINE_VISIBILITY void clear() {__tree_.clear();} diff --git a/include/module.modulemap b/include/module.modulemap index 127a42b06..3b66390fb 100644 --- a/include/module.modulemap +++ b/include/module.modulemap @@ -498,6 +498,7 @@ module std [system] { module __tree { header "__tree" export * } module __tuple { header "__tuple" export * } module __undef_macros { header "__undef_macros" export * } + module __node_handle { header "__node_handle" export * } module experimental { requires cplusplus11 diff --git a/include/set b/include/set index 94db8c79d..108a9e97f 100644 --- a/include/set +++ b/include/set @@ -40,6 +40,8 @@ public: typedef implementation-defined const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; + typedef unspecified node_type; // C++17 + typedef INSERT_RETURN_TYPE insert_return_type; // C++17 // construct/copy/destroy: set() @@ -115,6 +117,11 @@ public: void insert(InputIterator first, InputIterator last); void insert(initializer_list il); + node_type extract(const_iterator position); // C++17 + node_type extract(const key_type& x); // C++17 + insert_return_type insert(node_type&& nh); // C++17 + iterator insert(const_iterator hint, node_type&& nh); // C++17 + iterator erase(const_iterator position); iterator erase(iterator position); // C++14 size_type erase(const key_type& k); @@ -222,6 +229,7 @@ public: typedef implementation-defined const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; + typedef unspecified node_type; // C++17 // construct/copy/destroy: multiset() @@ -297,6 +305,11 @@ public: void insert(InputIterator first, InputIterator last); void insert(initializer_list il); + node_type extract(const_iterator position); // C++17 + node_type extract(const key_type& x); // C++17 + iterator insert(node_type&& nh); // C++17 + iterator insert(const_iterator hint, node_type&& nh); // C++17 + iterator erase(const_iterator position); iterator erase(iterator position); // C++14 size_type erase(const key_type& k); @@ -387,6 +400,7 @@ swap(multiset& x, multiset& y) #include <__config> #include <__tree> +#include <__node_handle> #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -429,6 +443,11 @@ public: typedef _VSTD::reverse_iterator reverse_iterator; typedef _VSTD::reverse_iterator const_reverse_iterator; +#if _LIBCPP_STD_VER > 14 + typedef __set_node_handle node_type; + typedef __insert_return_type insert_return_type; +#endif + _LIBCPP_INLINE_VISIBILITY set() _NOEXCEPT_( @@ -634,6 +653,35 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__tree_.clear();} +#if _LIBCPP_STD_VER > 14 + _LIBCPP_INLINE_VISIBILITY + insert_return_type insert(node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to set::insert()"); + return __tree_.template __node_handle_insert_unique< + node_type, insert_return_type>(_VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + iterator insert(const_iterator __hint, node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to set::insert()"); + return __tree_.template __node_handle_insert_unique( + __hint, _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(key_type const& __key) + { + return __tree_.template __node_handle_extract(__key); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(const_iterator __it) + { + return __tree_.template __node_handle_extract(__it); + } +#endif + _LIBCPP_INLINE_VISIBILITY void swap(set& __s) _NOEXCEPT_(__is_nothrow_swappable<__base>::value) {__tree_.swap(__s.__tree_);} @@ -838,6 +886,10 @@ public: typedef _VSTD::reverse_iterator reverse_iterator; typedef _VSTD::reverse_iterator const_reverse_iterator; +#if _LIBCPP_STD_VER > 14 + typedef __set_node_handle node_type; +#endif + // construct/copy/destroy: _LIBCPP_INLINE_VISIBILITY multiset() @@ -1042,6 +1094,35 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__tree_.clear();} +#if _LIBCPP_STD_VER > 14 + _LIBCPP_INLINE_VISIBILITY + iterator insert(node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to multiset::insert()"); + return __tree_.template __node_handle_insert_multi( + _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + iterator insert(const_iterator __hint, node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to multiset::insert()"); + return __tree_.template __node_handle_insert_multi( + __hint, _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(key_type const& __key) + { + return __tree_.template __node_handle_extract(__key); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(const_iterator __it) + { + return __tree_.template __node_handle_extract(__it); + } +#endif + _LIBCPP_INLINE_VISIBILITY void swap(multiset& __s) _NOEXCEPT_(__is_nothrow_swappable<__base>::value) diff --git a/include/unordered_map b/include/unordered_map index f34d82efd..348f57923 100644 --- a/include/unordered_map +++ b/include/unordered_map @@ -44,6 +44,9 @@ public: typedef /unspecified/ local_iterator; typedef /unspecified/ const_local_iterator; + typedef unspecified node_type; // C++17 + typedef INSERT_RETURN_TYPE insert_return_type; // C++17 + unordered_map() noexcept( is_nothrow_default_constructible::value && @@ -122,6 +125,11 @@ public: void insert(InputIterator first, InputIterator last); void insert(initializer_list); + node_type extract(const_iterator position); // C++17 + node_type extract(const key_type& x); // C++17 + insert_return_type insert(node_type&& nh); // C++17 + iterator insert(const_iterator hint, node_type&& nh); // C++17 + template pair try_emplace(const key_type& k, Args&&... args); // C++17 template @@ -226,6 +234,8 @@ public: typedef /unspecified/ local_iterator; typedef /unspecified/ const_local_iterator; + typedef unspecified node_type; // C++17 + unordered_multimap() noexcept( is_nothrow_default_constructible::value && @@ -304,6 +314,11 @@ public: void insert(InputIterator first, InputIterator last); void insert(initializer_list); + node_type extract(const_iterator position); // C++17 + node_type extract(const key_type& x); // C++17 + iterator insert(node_type&& nh); // C++17 + iterator insert(const_iterator hint, node_type&& nh); // C++17 + iterator erase(const_iterator position); iterator erase(iterator position); // C++14 size_type erase(const key_type& k); @@ -367,6 +382,7 @@ template #include <__config> #include <__hash_table> +#include <__node_handle> #include #include #include @@ -843,6 +859,11 @@ public: typedef __hash_map_iterator local_iterator; typedef __hash_map_const_iterator const_local_iterator; +#if _LIBCPP_STD_VER > 14 + typedef __map_node_handle<__node, allocator_type> node_type; + typedef __insert_return_type insert_return_type; +#endif + _LIBCPP_INLINE_VISIBILITY unordered_map() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) @@ -1136,7 +1157,37 @@ public: iterator erase(const_iterator __first, const_iterator __last) {return __table_.erase(__first.__i_, __last.__i_);} _LIBCPP_INLINE_VISIBILITY - void clear() _NOEXCEPT {__table_.clear();} + void clear() _NOEXCEPT {__table_.clear();} + +#if _LIBCPP_STD_VER > 14 + _LIBCPP_INLINE_VISIBILITY + insert_return_type insert(node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to unordered_map::insert()"); + return __table_.template __node_handle_insert_unique< + node_type, insert_return_type>(_VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + iterator insert(const_iterator __hint, node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to unordered_map::insert()"); + return __table_.template __node_handle_insert_unique( + __hint.__i_, _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(key_type const& __key) + { + return __table_.template __node_handle_extract(__key); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(const_iterator __it) + { + return __table_.template __node_handle_extract( + __it.__i_); + } +#endif _LIBCPP_INLINE_VISIBILITY void swap(unordered_map& __u) @@ -1590,6 +1641,10 @@ public: typedef __hash_map_iterator local_iterator; typedef __hash_map_const_iterator const_local_iterator; +#if _LIBCPP_STD_VER > 14 + typedef __map_node_handle<__node, allocator_type> node_type; +#endif + _LIBCPP_INLINE_VISIBILITY unordered_multimap() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) @@ -1763,6 +1818,36 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__table_.clear();} +#if _LIBCPP_STD_VER > 14 + _LIBCPP_INLINE_VISIBILITY + iterator insert(node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to unordered_multimap::insert()"); + return __table_.template __node_handle_insert_multi( + _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + iterator insert(const_iterator __hint, node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to unordered_multimap::insert()"); + return __table_.template __node_handle_insert_multi( + __hint.__i_, _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(key_type const& __key) + { + return __table_.template __node_handle_extract(__key); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(const_iterator __it) + { + return __table_.template __node_handle_extract( + __it.__i_); + } +#endif + _LIBCPP_INLINE_VISIBILITY void swap(unordered_multimap& __u) _NOEXCEPT_(__is_nothrow_swappable<__table>::value) diff --git a/include/unordered_set b/include/unordered_set index 3ae024a45..9b8560da4 100644 --- a/include/unordered_set +++ b/include/unordered_set @@ -43,6 +43,9 @@ public: typedef /unspecified/ local_iterator; typedef /unspecified/ const_local_iterator; + typedef unspecified node_type unspecified; // C++17 + typedef INSERT_RETURN_TYPE insert_return_type; // C++17 + unordered_set() noexcept( is_nothrow_default_constructible::value && @@ -113,6 +116,11 @@ public: void insert(InputIterator first, InputIterator last); void insert(initializer_list); + node_type extract(const_iterator position); // C++17 + node_type extract(const key_type& x); // C++17 + insert_return_type insert(node_type&& nh); // C++17 + iterator insert(const_iterator hint, node_type&& nh); // C++17 + iterator erase(const_iterator position); iterator erase(iterator position); // C++14 size_type erase(const key_type& k); @@ -191,6 +199,8 @@ public: typedef /unspecified/ local_iterator; typedef /unspecified/ const_local_iterator; + typedef unspecified node_type unspecified; // C++17 + unordered_multiset() noexcept( is_nothrow_default_constructible::value && @@ -261,6 +271,11 @@ public: void insert(InputIterator first, InputIterator last); void insert(initializer_list); + node_type extract(const_iterator position); // C++17 + node_type extract(const key_type& x); // C++17 + iterator insert(node_type&& nh); // C++17 + iterator insert(const_iterator hint, node_type&& nh); // C++17 + iterator erase(const_iterator position); iterator erase(iterator position); // C++14 size_type erase(const key_type& k); @@ -321,6 +336,7 @@ template #include <__config> #include <__hash_table> +#include <__node_handle> #include #include <__debug> @@ -363,6 +379,11 @@ public: typedef typename __table::const_local_iterator local_iterator; typedef typename __table::const_local_iterator const_local_iterator; +#if _LIBCPP_STD_VER > 14 + typedef __set_node_handle node_type; + typedef __insert_return_type insert_return_type; +#endif + _LIBCPP_INLINE_VISIBILITY unordered_set() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) @@ -541,6 +562,35 @@ public: _LIBCPP_INLINE_VISIBILITY void clear() _NOEXCEPT {__table_.clear();} +#if _LIBCPP_STD_VER > 14 + _LIBCPP_INLINE_VISIBILITY + insert_return_type insert(node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to unordered_set::insert()"); + return __table_.template __node_handle_insert_unique< + node_type, insert_return_type>(_VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + iterator insert(const_iterator __h, node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to unordered_set::insert()"); + return __table_.template __node_handle_insert_unique( + __h, _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(key_type const& __key) + { + return __table_.template __node_handle_extract(__key); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(const_iterator __it) + { + return __table_.template __node_handle_extract(__it); + } +#endif + _LIBCPP_INLINE_VISIBILITY void swap(unordered_set& __u) _NOEXCEPT_(__is_nothrow_swappable<__table>::value) @@ -883,6 +933,10 @@ public: typedef typename __table::const_local_iterator local_iterator; typedef typename __table::const_local_iterator const_local_iterator; +#if _LIBCPP_STD_VER > 14 + typedef __set_node_handle node_type; +#endif + _LIBCPP_INLINE_VISIBILITY unordered_multiset() _NOEXCEPT_(is_nothrow_default_constructible<__table>::value) @@ -1019,6 +1073,36 @@ public: _LIBCPP_INLINE_VISIBILITY void insert(_InputIterator __first, _InputIterator __last); +#if _LIBCPP_STD_VER > 14 + _LIBCPP_INLINE_VISIBILITY + iterator insert(node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to unordered_multiset::insert()"); + return __table_.template __node_handle_insert_multi( + _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + iterator insert(const_iterator __hint, node_type&& __nh) + { + _LIBCPP_ASSERT(__nh.empty() || __nh.get_allocator() == get_allocator(), + "node_type with incompatible allocator passed to unordered_multiset::insert()"); + return __table_.template __node_handle_insert_multi( + __hint, _VSTD::move(__nh)); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(const_iterator __position) + { + return __table_.template __node_handle_extract( + __position); + } + _LIBCPP_INLINE_VISIBILITY + node_type extract(key_type const& __key) + { + return __table_.template __node_handle_extract(__key); + } +#endif + _LIBCPP_INLINE_VISIBILITY iterator erase(const_iterator __p) {return __table_.erase(__p);} _LIBCPP_INLINE_VISIBILITY diff --git a/test/std/containers/associative/map/map.modifiers/extract_iterator.pass.cpp b/test/std/containers/associative/map/map.modifiers/extract_iterator.pass.cpp new file mode 100644 index 000000000..ea7fd8907 --- /dev/null +++ b/test/std/containers/associative/map/map.modifiers/extract_iterator.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class map + +// node_type extract(const_iterator); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c) +{ + size_t sz = c.size(); + + auto some_key = c.cbegin()->first; + + for (auto first = c.cbegin(); first != c.cend();) + { + auto key_value = first->first; + typename Container::node_type t = c.extract(first++); + --sz; + assert(t.key() == key_value); + t.key() = some_key; + assert(t.key() == some_key); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); +} + +int main() +{ + { + using map_type = std::map; + map_type m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + test(m); + } + + { + std::map, Counter> m = + {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + assert(Counter_base::gConstructed == 12); + test(m); + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_map = + std::map, + min_allocator>>; + min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}}; + test(m); + } +} diff --git a/test/std/containers/associative/map/map.modifiers/extract_key.pass.cpp b/test/std/containers/associative/map/map.modifiers/extract_key.pass.cpp new file mode 100644 index 000000000..41cd09300 --- /dev/null +++ b/test/std/containers/associative/map/map.modifiers/extract_key.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class map + +// node_type extract(key_type const&); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c, KeyTypeIter first, KeyTypeIter last) +{ + size_t sz = c.size(); + assert((size_t)std::distance(first, last) == sz); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(!t.empty()); + --sz; + assert(t.key() == *copy); + t.key() = *first; // We should be able to mutate key. + assert(t.key() == *first); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(t.empty()); + } +} + +int main() +{ + { + std::map m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } + + { + std::map, Counter> m = + {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + { + Counter keys[] = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 12+6); + test(m, std::begin(keys), std::end(keys)); + } + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_map = + std::map, + min_allocator>>; + min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } +} diff --git a/test/std/containers/associative/map/map.modifiers/insert_node_type.pass.cpp b/test/std/containers/associative/map/map.modifiers/insert_node_type.pass.cpp new file mode 100644 index 000000000..cc1704c30 --- /dev/null +++ b/test/std/containers/associative/map/map.modifiers/insert_node_type.pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class map + +// insert_return_type insert(node_type&&); + +#include +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key, + typename Container::mapped_type const& mapped) +{ + static Container c; + auto p = c.insert({key, mapped}); + assert(p.second); + return c.extract(p.first); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i, i + 1); + assert(!node.empty()); + typename Container::insert_return_type irt = c.insert(std::move(node)); + assert(node.empty()); + assert(irt.inserted); + assert(irt.node.empty()); + assert(irt.position->first == i && irt.position->second == i + 1); + } + + assert(c.size() == 10); + + { // Insert empty node. + typename Container::node_type def; + auto irt = c.insert(std::move(def)); + assert(def.empty()); + assert(!irt.inserted); + assert(irt.node.empty()); + assert(irt.position == c.end()); + } + + { // Insert duplicate node. + typename Container::node_type dupl = nf(0, 42); + auto irt = c.insert(std::move(dupl)); + assert(dupl.empty()); + assert(!irt.inserted); + assert(!irt.node.empty()); + assert(irt.position == c.find(0)); + assert(irt.node.key() == 0 && irt.node.mapped() == 42); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + assert(c[i] == i + 1); + } +} + +int main() +{ + std::map m; + test(m); + std::map, min_allocator>> m2; + test(m2); +} diff --git a/test/std/containers/associative/map/map.modifiers/insert_node_type_hint.pass.cpp b/test/std/containers/associative/map/map.modifiers/insert_node_type_hint.pass.cpp new file mode 100644 index 000000000..3c6b3e31a --- /dev/null +++ b/test/std/containers/associative/map/map.modifiers/insert_node_type_hint.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class map + +// iterator insert(const_iterator hint, node_type&&); + +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key, + typename Container::mapped_type const& mapped) +{ + static Container c; + auto p = c.insert({key, mapped}); + assert(p.second); + return c.extract(p.first); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i, i + 1); + assert(!node.empty()); + size_t prev = c.size(); + auto it = c.insert(c.end(), std::move(node)); + assert(node.empty()); + assert(prev + 1 == c.size()); + assert(it->first == i); + assert(it->second == i + 1); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + assert(c[i] == i + 1); + } +} + +int main() +{ + std::map m; + test(m); + std::map, min_allocator>> m2; + test(m2); +} diff --git a/test/std/containers/associative/multimap/multimap.modifiers/extract_iterator.pass.cpp b/test/std/containers/associative/multimap/multimap.modifiers/extract_iterator.pass.cpp new file mode 100644 index 000000000..3e00d2b98 --- /dev/null +++ b/test/std/containers/associative/multimap/multimap.modifiers/extract_iterator.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class multimap + +// node_type extract(const_iterator); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c) +{ + size_t sz = c.size(); + + auto some_key = c.cbegin()->first; + + for (auto first = c.cbegin(); first != c.cend();) + { + auto key_value = first->first; + typename Container::node_type t = c.extract(first++); + --sz; + assert(t.key() == key_value); + t.key() = some_key; + assert(t.key() == some_key); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); +} + +int main() +{ + { + using map_type = std::multimap; + map_type m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + test(m); + } + + { + std::multimap, Counter> m = + {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + assert(Counter_base::gConstructed == 12); + test(m); + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_map = + std::multimap, + min_allocator>>; + min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}}; + test(m); + } +} diff --git a/test/std/containers/associative/multimap/multimap.modifiers/extract_key.pass.cpp b/test/std/containers/associative/multimap/multimap.modifiers/extract_key.pass.cpp new file mode 100644 index 000000000..ca69cca6b --- /dev/null +++ b/test/std/containers/associative/multimap/multimap.modifiers/extract_key.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class multimap + +// node_type extract(key_type const&); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c, KeyTypeIter first, KeyTypeIter last) +{ + size_t sz = c.size(); + assert((size_t)std::distance(first, last) == sz); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(!t.empty()); + --sz; + assert(t.key() == *copy); + t.key() = *first; // We should be able to mutate key. + assert(t.key() == *first); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(t.empty()); + } +} + +int main() +{ + { + std::multimap m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } + + { + std::multimap, Counter> m = + {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + { + Counter keys[] = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 12+6); + test(m, std::begin(keys), std::end(keys)); + } + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_map = + std::multimap, + min_allocator>>; + min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } +} diff --git a/test/std/containers/associative/multimap/multimap.modifiers/insert_node_type.pass.cpp b/test/std/containers/associative/multimap/multimap.modifiers/insert_node_type.pass.cpp new file mode 100644 index 000000000..906770514 --- /dev/null +++ b/test/std/containers/associative/multimap/multimap.modifiers/insert_node_type.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class multimap + +// iterator insert(node_type&&); + +#include +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key, + typename Container::mapped_type const& mapped) +{ + static Container c; + auto it = c.insert({key, mapped}); + return c.extract(it); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i, i + 1); + assert(!node.empty()); + typename Container::iterator it = c.insert(std::move(node)); + assert(node.empty()); + assert(it == c.find(i) && it != c.end()); + } + + assert(c.size() == 10); + + { // Insert empty node. + typename Container::node_type def; + auto it = c.insert(std::move(def)); + assert(def.empty()); + assert(it == c.end()); + } + + { // Insert duplicate node. + typename Container::node_type dupl = nf(0, 42); + auto it = c.insert(std::move(dupl)); + assert(dupl.empty()); + assert(it != c.end()); + assert(it->second == 42); + } + + assert(c.size() == 11); + assert(c.count(0) == 2); + for (int i = 1; i != 10; ++i) + { + assert(c.count(i) == 1); + assert(c.find(i)->second == i + 1); + } +} + +int main() +{ + std::multimap m; + test(m); + std::multimap, min_allocator>> m2; + test(m2); +} diff --git a/test/std/containers/associative/multimap/multimap.modifiers/insert_node_type_hint.pass.cpp b/test/std/containers/associative/multimap/multimap.modifiers/insert_node_type_hint.pass.cpp new file mode 100644 index 000000000..82e7d80c0 --- /dev/null +++ b/test/std/containers/associative/multimap/multimap.modifiers/insert_node_type_hint.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class multimap + +// iterator insert(const_iterator hint, node_type&&); + +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key, + typename Container::mapped_type const& mapped) +{ + static Container c; + auto it = c.insert({key, mapped}); + return c.extract(it); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i, i + 1); + assert(!node.empty()); + size_t prev = c.size(); + auto it = c.insert(c.end(), std::move(node)); + assert(node.empty()); + assert(prev + 1 == c.size()); + assert(it == c.find(i)); + assert(it->first == i); + assert(it->second == i + 1); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + assert(c.find(i)->second == i + 1); + } +} + +int main() +{ + std::multimap m; + test(m); + std::multimap, min_allocator>> m2; + test(m2); +} diff --git a/test/std/containers/associative/multiset/extract_iterator.pass.cpp b/test/std/containers/associative/multiset/extract_iterator.pass.cpp new file mode 100644 index 000000000..0f41169e9 --- /dev/null +++ b/test/std/containers/associative/multiset/extract_iterator.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class multiset + +// node_type extract(const_iterator); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c) +{ + size_t sz = c.size(); + + for (auto first = c.cbegin(); first != c.cend();) + { + auto key_value = *first; + typename Container::node_type t = c.extract(first++); + --sz; + assert(t.value() == key_value); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); +} + +int main() +{ + { + using set_type = std::multiset; + set_type m = {1, 2, 3, 4, 5, 6}; + test(m); + } + + { + std::multiset> m = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 6); + test(m); + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_set = std::multiset, min_allocator>; + min_alloc_set m = {1, 2, 3, 4, 5, 6}; + test(m); + } +} diff --git a/test/std/containers/associative/multiset/extract_key.pass.cpp b/test/std/containers/associative/multiset/extract_key.pass.cpp new file mode 100644 index 000000000..9ad018410 --- /dev/null +++ b/test/std/containers/associative/multiset/extract_key.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class multiset + +// node_type extract(key_type const&); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c, KeyTypeIter first, KeyTypeIter last) +{ + size_t sz = c.size(); + assert((size_t)std::distance(first, last) == sz); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(!t.empty()); + --sz; + assert(t.value() == *copy); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(t.empty()); + } +} + +int main() +{ + { + std::multiset m = {1, 2, 3, 4, 5, 6}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } + + { + std::multiset> m = {1, 2, 3, 4, 5, 6}; + { + Counter keys[] = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 6+6); + test(m, std::begin(keys), std::end(keys)); + } + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_set = std::multiset, min_allocator>; + min_alloc_set m = {1, 2, 3, 4, 5, 6}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } +} diff --git a/test/std/containers/associative/multiset/insert_node_type.pass.cpp b/test/std/containers/associative/multiset/insert_node_type.pass.cpp new file mode 100644 index 000000000..ca51ec9f0 --- /dev/null +++ b/test/std/containers/associative/multiset/insert_node_type.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class multiset + +// iterator insert(node_type&&); + +#include +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key) +{ + static Container c; + auto it = c.insert(key); + return c.extract(it); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i); + assert(!node.empty()); + typename Container::iterator it = c.insert(std::move(node)); + assert(node.empty()); + assert(it == c.find(i) && it != c.end()); + assert(*it == i); + assert(node.empty()); + } + + assert(c.size() == 10); + + { // Insert empty node. + typename Container::node_type def; + auto it = c.insert(std::move(def)); + assert(def.empty()); + assert(it == c.end()); + } + + { // Insert duplicate node. + typename Container::node_type dupl = nf(0); + auto it = c.insert(std::move(dupl)); + assert(*it == 0); + } + + assert(c.size() == 11); + + assert(c.count(0) == 2); + for (int i = 1; i != 10; ++i) + { + assert(c.count(i) == 1); + } +} + +int main() +{ + std::multiset m; + test(m); + std::multiset, min_allocator> m2; + test(m2); +} diff --git a/test/std/containers/associative/multiset/insert_node_type_hint.pass.cpp b/test/std/containers/associative/multiset/insert_node_type_hint.pass.cpp new file mode 100644 index 000000000..9d0af0653 --- /dev/null +++ b/test/std/containers/associative/multiset/insert_node_type_hint.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class multiset + +// iterator insert(const_iterator hint, node_type&&); + +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key) +{ + static Container c; + auto it = c.insert(key); + return c.extract(it); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i); + assert(!node.empty()); + size_t prev = c.size(); + auto it = c.insert(c.end(), std::move(node)); + assert(prev + 1 == c.size()); + assert(*it == i); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + } +} + +int main() +{ + std::multiset m; + test(m); + std::multiset, min_allocator> m2; + test(m2); +} diff --git a/test/std/containers/associative/set/extract_iterator.pass.cpp b/test/std/containers/associative/set/extract_iterator.pass.cpp new file mode 100644 index 000000000..ffcf71486 --- /dev/null +++ b/test/std/containers/associative/set/extract_iterator.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class set + +// node_type extract(const_iterator); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c) +{ + size_t sz = c.size(); + + for (auto first = c.cbegin(); first != c.cend();) + { + auto key_value = *first; + typename Container::node_type t = c.extract(first++); + --sz; + assert(t.value() == key_value); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); +} + +int main() +{ + { + using set_type = std::set; + set_type m = {1, 2, 3, 4, 5, 6}; + test(m); + } + + { + std::set> m = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 6); + test(m); + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_set = std::set, min_allocator>; + min_alloc_set m = {1, 2, 3, 4, 5, 6}; + test(m); + } +} diff --git a/test/std/containers/associative/set/extract_key.pass.cpp b/test/std/containers/associative/set/extract_key.pass.cpp new file mode 100644 index 000000000..1fb7ab911 --- /dev/null +++ b/test/std/containers/associative/set/extract_key.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class set + +// node_type extract(key_type const&); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c, KeyTypeIter first, KeyTypeIter last) +{ + size_t sz = c.size(); + assert((size_t)std::distance(first, last) == sz); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(!t.empty()); + --sz; + assert(t.value() == *copy); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(t.empty()); + } +} + +int main() +{ + { + std::set m = {1, 2, 3, 4, 5, 6}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } + + { + std::set> m = {1, 2, 3, 4, 5, 6}; + { + Counter keys[] = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 6+6); + test(m, std::begin(keys), std::end(keys)); + } + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_set = std::set, min_allocator>; + min_alloc_set m = {1, 2, 3, 4, 5, 6}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } +} diff --git a/test/std/containers/associative/set/insert_node_type.pass.cpp b/test/std/containers/associative/set/insert_node_type.pass.cpp new file mode 100644 index 000000000..4186f20e7 --- /dev/null +++ b/test/std/containers/associative/set/insert_node_type.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class set + +// insert_return_type insert(node_type&&); + +#include +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key) +{ + static Container c; + auto p = c.insert(key); + assert(p.second); + return c.extract(p.first); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i); + assert(!node.empty()); + typename Container::insert_return_type irt = c.insert(std::move(node)); + assert(node.empty()); + assert(irt.inserted); + assert(irt.node.empty()); + assert(*irt.position == i); + } + + assert(c.size() == 10); + + { // Insert empty node. + typename Container::node_type def; + auto irt = c.insert(std::move(def)); + assert(def.empty()); + assert(!irt.inserted); + assert(irt.node.empty()); + assert(irt.position == c.end()); + } + + { // Insert duplicate node. + typename Container::node_type dupl = nf(0); + auto irt = c.insert(std::move(dupl)); + assert(dupl.empty()); + assert(!irt.inserted); + assert(!irt.node.empty()); + assert(irt.position == c.find(0)); + assert(irt.node.value() == 0); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + } +} + +int main() +{ + std::set m; + test(m); + std::set, min_allocator> m2; + test(m2); +} diff --git a/test/std/containers/associative/set/insert_node_type_hint.pass.cpp b/test/std/containers/associative/set/insert_node_type_hint.pass.cpp new file mode 100644 index 000000000..761ceef6a --- /dev/null +++ b/test/std/containers/associative/set/insert_node_type_hint.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class set + +// iterator insert(const_iterator hint, node_type&&); + +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key) +{ + static Container c; + auto p = c.insert(key); + assert(p.second); + return c.extract(p.first); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i); + assert(!node.empty()); + size_t prev = c.size(); + auto it = c.insert(c.end(), std::move(node)); + assert(node.empty()); + assert(prev + 1 == c.size()); + assert(*it == i); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + } +} + +int main() +{ + std::set m; + test(m); + std::set, min_allocator> m2; + test(m2); +} diff --git a/test/std/containers/container.node/node_handle.pass.cpp b/test/std/containers/container.node/node_handle.pass.cpp new file mode 100644 index 000000000..6314ec1fb --- /dev/null +++ b/test/std/containers/container.node/node_handle.pass.cpp @@ -0,0 +1,145 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +#include +#include +#include +#include +#include "min_allocator.h" + +using namespace std; + +// [container.node.overview] Table 83. +template +struct node_compatibility_table +{ + static constexpr bool value = + is_same_v::node_type, typename map::node_type> && + is_same_v::node_type, typename multimap::node_type> && + is_same_v::node_type, typename set::node_type> && + is_same_v::node_type, typename multiset::node_type> && + is_same_v::node_type, typename unordered_map::node_type> && + is_same_v::node_type, typename unordered_multimap::node_type> && + is_same_v::node_type, typename unordered_set::node_type> && + is_same_v::node_type, typename unordered_multiset::node_type>; +}; + +template struct my_hash +{ + using argument_type = T; + using result_type = size_t; + my_hash() = default; + size_t operator()(const T&) const {return 0;} +}; + +template struct my_compare +{ + my_compare() = default; + bool operator()(const T&, const T&) const {return true;} +}; + +template struct my_equal +{ + my_equal() = default; + bool operator()(const T&, const T&) const {return true;} +}; + +struct Static +{ + Static() = default; + Static(const Static&) = delete; + Static(Static&&) = delete; + Static& operator=(const Static&) = delete; + Static& operator=(Static&&) = delete; +}; + +namespace std +{ +template <> struct hash +{ + using argument_type = Static; + using result_type = size_t; + hash() = default; + size_t operator()(const Static&) const; +}; +} + +static_assert(node_compatibility_table< + int, int, std::less, std::less, std::hash, + std::hash, std::equal_to, std::equal_to, + std::allocator, + std::allocator>>::value, + ""); + +static_assert( + node_compatibility_table, my_compare, + std::hash, my_hash, std::equal_to, + my_equal, allocator, + allocator>>::value, + ""); + +static_assert(node_compatibility_table< + Static, int, my_compare, std::less, + my_hash, std::hash, my_equal, + std::equal_to, min_allocator, + min_allocator>>::value, + ""); + +template +void test_node_handle_operations() +{ + Container c; + + typename Container::node_type nt1, nt2 = c.extract(c.emplace().first); + assert(nt2.get_allocator() == c.get_allocator()); + assert(!nt2.empty()); + assert(nt1.empty()); + std::swap(nt1, nt2); + assert(nt1.get_allocator() == c.get_allocator()); + assert(nt2.empty()); +} + +template +void test_node_handle_operations_multi() +{ + Container c; + + typename Container::node_type nt1, nt2 = c.extract(c.emplace()); + assert(nt2.get_allocator() == c.get_allocator()); + assert(!nt2.empty()); + assert(nt1.empty()); + std::swap(nt1, nt2); + assert(nt1.get_allocator() == c.get_allocator()); + assert(nt2.empty()); +} + +template +void test_insert_return_type() +{ + using irt_type = typename Container::insert_return_type; +} + +int main() +{ + test_node_handle_operations>(); + test_node_handle_operations_multi>(); + test_node_handle_operations>(); + test_node_handle_operations_multi>(); + test_node_handle_operations>(); + test_node_handle_operations_multi>(); + test_node_handle_operations>(); + test_node_handle_operations_multi>(); + + test_insert_return_type>(); + test_insert_return_type>(); + test_insert_return_type>(); + test_insert_return_type>(); +} diff --git a/test/std/containers/unord/unord.map/unord.map.modifiers/extract_iterator.pass.cpp b/test/std/containers/unord/unord.map/unord.map.modifiers/extract_iterator.pass.cpp new file mode 100644 index 000000000..4cc13ded2 --- /dev/null +++ b/test/std/containers/unord/unord.map/unord.map.modifiers/extract_iterator.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_map + +// node_type extract(const_iterator); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c) +{ + size_t sz = c.size(); + + auto some_key = c.cbegin()->first; + + for (auto first = c.cbegin(); first != c.cend();) + { + auto key_value = first->first; + typename Container::node_type t = c.extract(first++); + --sz; + assert(t.key() == key_value); + t.key() = some_key; + assert(t.key() == some_key); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); +} + +int main() +{ + { + using map_type = std::unordered_map; + map_type m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + test(m); + } + + { + std::unordered_map, Counter> m = + {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + assert(Counter_base::gConstructed == 12); + test(m); + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_map = + std::unordered_map, std::equal_to, + min_allocator>>; + min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}}; + test(m); + } +} diff --git a/test/std/containers/unord/unord.map/unord.map.modifiers/extract_key.pass.cpp b/test/std/containers/unord/unord.map/unord.map.modifiers/extract_key.pass.cpp new file mode 100644 index 000000000..25aa24888 --- /dev/null +++ b/test/std/containers/unord/unord.map/unord.map.modifiers/extract_key.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_map + +// node_type extract(key_type const&); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c, KeyTypeIter first, KeyTypeIter last) +{ + size_t sz = c.size(); + assert((size_t)std::distance(first, last) == sz); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(!t.empty()); + --sz; + assert(t.key() == *copy); + t.key() = *first; // We should be able to mutate key. + assert(t.key() == *first); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(t.empty()); + } +} + +int main() +{ + { + std::unordered_map m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } + + { + std::unordered_map, Counter> m = + {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + { + Counter keys[] = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 12+6); + test(m, std::begin(keys), std::end(keys)); + } + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_map = + std::unordered_map, std::equal_to, + min_allocator>>; + min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } +} diff --git a/test/std/containers/unord/unord.map/unord.map.modifiers/insert_node_type.pass.cpp b/test/std/containers/unord/unord.map/unord.map.modifiers/insert_node_type.pass.cpp new file mode 100644 index 000000000..d43486488 --- /dev/null +++ b/test/std/containers/unord/unord.map/unord.map.modifiers/insert_node_type.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_map + +// insert_return_type insert(node_type&&); + +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key, + typename Container::mapped_type const& mapped) +{ + static Container c; + auto p = c.insert({key, mapped}); + assert(p.second); + return c.extract(p.first); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i, i + 1); + assert(!node.empty()); + typename Container::insert_return_type irt = c.insert(std::move(node)); + assert(node.empty()); + assert(irt.inserted); + assert(irt.node.empty()); + assert(irt.position->first == i && irt.position->second == i + 1); + } + + assert(c.size() == 10); + + { // Insert empty node. + typename Container::node_type def; + auto irt = c.insert(std::move(def)); + assert(def.empty()); + assert(!irt.inserted); + assert(irt.node.empty()); + assert(irt.position == c.end()); + } + + { // Insert duplicate node. + typename Container::node_type dupl = nf(0, 42); + auto irt = c.insert(std::move(dupl)); + assert(dupl.empty()); + assert(!irt.inserted); + assert(!irt.node.empty()); + assert(irt.position == c.find(0)); + assert(irt.node.key() == 0 && irt.node.mapped() == 42); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + assert(c[i] == i + 1); + } +} + +int main() +{ + std::unordered_map m; + test(m); + std::unordered_map, std::equal_to, min_allocator>> m2; + test(m2); +} diff --git a/test/std/containers/unord/unord.map/unord.map.modifiers/insert_node_type_hint.pass.cpp b/test/std/containers/unord/unord.map/unord.map.modifiers/insert_node_type_hint.pass.cpp new file mode 100644 index 000000000..ef98453b6 --- /dev/null +++ b/test/std/containers/unord/unord.map/unord.map.modifiers/insert_node_type_hint.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_map + +// iterator insert(const_iterator hint, node_type&&); + +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key, + typename Container::mapped_type const& mapped) +{ + static Container c; + auto p = c.insert({key, mapped}); + assert(p.second); + return c.extract(p.first); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i, i + 1); + assert(!node.empty()); + size_t prev = c.size(); + auto it = c.insert(c.end(), std::move(node)); + assert(node.empty()); + assert(prev + 1 == c.size()); + assert(it->first == i); + assert(it->second == i + 1); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + assert(c[i] == i + 1); + } +} + +int main() +{ + std::unordered_map m; + test(m); + std::unordered_map, std::equal_to, min_allocator>> m2; + test(m2); +} diff --git a/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/extract_iterator.pass.cpp b/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/extract_iterator.pass.cpp new file mode 100644 index 000000000..adb2ddb2b --- /dev/null +++ b/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/extract_iterator.pass.cpp @@ -0,0 +1,67 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_multimap + +// node_type extract(const_iterator); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c) +{ + size_t sz = c.size(); + + auto some_key = c.cbegin()->first; + + for (auto first = c.cbegin(); first != c.cend();) + { + auto key_value = first->first; + typename Container::node_type t = c.extract(first++); + --sz; + assert(t.key() == key_value); + t.key() = some_key; + assert(t.key() == some_key); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); +} + +int main() +{ + { + using map_type = std::unordered_multimap; + map_type m = {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + test(m); + } + + { + std::unordered_multimap, Counter> m = + {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + assert(Counter_base::gConstructed == 12); + test(m); + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_map = + std::unordered_multimap, std::equal_to, + min_allocator>>; + min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}}; + test(m); + } +} diff --git a/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/extract_key.pass.cpp b/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/extract_key.pass.cpp new file mode 100644 index 000000000..8cf26fc77 --- /dev/null +++ b/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/extract_key.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_multimap + +// node_type extract(key_type const&); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c, KeyTypeIter first, KeyTypeIter last) +{ + size_t sz = c.size(); + assert((size_t)std::distance(first, last) == sz); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(!t.empty()); + --sz; + assert(t.key() == *copy); + t.key() = *first; // We should be able to mutate key. + assert(t.key() == *first); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(t.empty()); + } +} + +int main() +{ + { + std::unordered_multimap m = + {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } + + { + std::unordered_multimap, Counter> m = + {{1,1}, {2,2}, {3,3}, {4,4}, {5,5}, {6,6}}; + { + Counter keys[] = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 12+6); + test(m, std::begin(keys), std::end(keys)); + } + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_map = + std::unordered_multimap, std::equal_to, + min_allocator>>; + min_alloc_map m = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}, {6, 6}}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } +} diff --git a/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_node_type.pass.cpp b/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_node_type.pass.cpp new file mode 100644 index 000000000..93c0462b3 --- /dev/null +++ b/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_node_type.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_multimap + +// iterator insert(node_type&&); + +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key, + typename Container::mapped_type const& mapped) +{ + static Container c; + auto it = c.insert({key, mapped}); + return c.extract(it); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i, i + 1); + assert(!node.empty()); + typename Container::iterator it = c.insert(std::move(node)); + assert(node.empty()); + assert(it == c.find(i) && it != c.end()); + assert(it->first == i && it->second == i + 1); + } + + assert(c.size() == 10); + + { // Insert empty node. + typename Container::node_type def; + auto it = c.insert(std::move(def)); + assert(def.empty()); + assert(it == c.end()); + } + + { // Insert duplicate node. + typename Container::node_type dupl = nf(0, 42); + auto it = c.insert(std::move(dupl)); + assert(dupl.empty()); + assert(it != c.end() && it->second == 42); + } + + assert(c.size() == 11); + assert(c.count(0) == 2); + for (int i = 1; i != 10; ++i) + { + assert(c.count(i) == 1); + assert(c.find(i)->second == i + 1); + } +} + +int main() +{ + std::unordered_multimap m; + test(m); + std::unordered_multimap, std::equal_to, min_allocator>> m2; + test(m2); +} diff --git a/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_node_type_hint.pass.cpp b/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_node_type_hint.pass.cpp new file mode 100644 index 000000000..99a47cabb --- /dev/null +++ b/test/std/containers/unord/unord.multimap/unord.multimap.modifiers/insert_node_type_hint.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_multimap + +// iterator insert(const_iterator hint, node_type&&); + +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key, + typename Container::mapped_type const& mapped) +{ + static Container c; + auto it = c.insert({key, mapped}); + return c.extract(it); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i, i + 1); + assert(!node.empty()); + size_t prev = c.size(); + auto it = c.insert(c.end(), std::move(node)); + assert(node.empty()); + assert(prev + 1 == c.size()); + assert(it->first == i); + assert(it->second == i + 1); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + assert(c.find(i)->second == i + 1); + } +} + +int main() +{ + std::unordered_multimap m; + test(m); + std::unordered_multimap, std::equal_to, min_allocator>> m2; + test(m2); +} diff --git a/test/std/containers/unord/unord.multiset/extract_iterator.pass.cpp b/test/std/containers/unord/unord.multiset/extract_iterator.pass.cpp new file mode 100644 index 000000000..1595c55a4 --- /dev/null +++ b/test/std/containers/unord/unord.multiset/extract_iterator.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_multiset + +// node_type extract(const_iterator); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c) +{ + size_t sz = c.size(); + + for (auto first = c.cbegin(); first != c.cend();) + { + auto key_value = *first; + typename Container::node_type t = c.extract(first++); + --sz; + assert(t.value() == key_value); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); +} + +int main() +{ + { + using set_type = std::unordered_multiset; + set_type m = {1, 2, 3, 4, 5, 6}; + test(m); + } + + { + std::unordered_multiset> m = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 6); + test(m); + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_set = std::unordered_multiset, std::equal_to, min_allocator>; + min_alloc_set m = {1, 2, 3, 4, 5, 6}; + test(m); + } +} diff --git a/test/std/containers/unord/unord.multiset/extract_key.pass.cpp b/test/std/containers/unord/unord.multiset/extract_key.pass.cpp new file mode 100644 index 000000000..ffe46fb30 --- /dev/null +++ b/test/std/containers/unord/unord.multiset/extract_key.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_multiset + +// node_type extract(key_type const&); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c, KeyTypeIter first, KeyTypeIter last) +{ + size_t sz = c.size(); + assert((size_t)std::distance(first, last) == sz); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(!t.empty()); + --sz; + assert(t.value() == *copy); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(t.empty()); + } +} + +int main() +{ + { + std::unordered_multiset m = {1, 2, 3, 4, 5, 6}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } + + { + std::unordered_multiset> m = {1, 2, 3, 4, 5, 6}; + { + Counter keys[] = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 6+6); + test(m, std::begin(keys), std::end(keys)); + } + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_set = std::unordered_multiset, std::equal_to, min_allocator>; + min_alloc_set m = {1, 2, 3, 4, 5, 6}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } +} diff --git a/test/std/containers/unord/unord.multiset/insert_node_type.pass.cpp b/test/std/containers/unord/unord.multiset/insert_node_type.pass.cpp new file mode 100644 index 000000000..c3d4cd2a0 --- /dev/null +++ b/test/std/containers/unord/unord.multiset/insert_node_type.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_multiset + +// iterator insert(node_type&&); + +#include +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key) +{ + static Container c; + auto it = c.insert(key); + return c.extract(it); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i); + assert(!node.empty()); + typename Container::iterator it = c.insert(std::move(node)); + assert(node.empty()); + assert(it == c.find(i) && it != c.end()); + assert(*it == i); + assert(node.empty()); + } + + assert(c.size() == 10); + + { // Insert empty node. + typename Container::node_type def; + auto it = c.insert(std::move(def)); + assert(def.empty()); + assert(it == c.end()); + } + + { // Insert duplicate node. + typename Container::node_type dupl = nf(0); + auto it = c.insert(std::move(dupl)); + assert(*it == 0); + } + + assert(c.size() == 11); + assert(c.count(0) == 2); + for (int i = 1; i != 10; ++i) + { + assert(c.count(i) == 1); + } +} + +int main() +{ + std::unordered_multiset m; + test(m); + std::unordered_multiset, std::equal_to, min_allocator> m2; + test(m2); +} diff --git a/test/std/containers/unord/unord.multiset/insert_node_type_hint.pass.cpp b/test/std/containers/unord/unord.multiset/insert_node_type_hint.pass.cpp new file mode 100644 index 000000000..79712d3de --- /dev/null +++ b/test/std/containers/unord/unord.multiset/insert_node_type_hint.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_multiset + +// iterator insert(const_iterator hint, node_type&&); + +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key) +{ + static Container c; + auto it = c.insert(key); + return c.extract(it); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i); + assert(!node.empty()); + size_t prev = c.size(); + auto it = c.insert(c.end(), std::move(node)); + assert(prev + 1 == c.size()); + assert(*it == i); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + } +} + +int main() +{ + std::unordered_multiset m; + test(m); + std::unordered_multiset, std::equal_to, min_allocator> m2; + test(m2); +} diff --git a/test/std/containers/unord/unord.set/extract_iterator.pass.cpp b/test/std/containers/unord/unord.set/extract_iterator.pass.cpp new file mode 100644 index 000000000..40feb0e2f --- /dev/null +++ b/test/std/containers/unord/unord.set/extract_iterator.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_set + +// node_type extract(const_iterator); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c) +{ + size_t sz = c.size(); + + for (auto first = c.cbegin(); first != c.cend();) + { + auto key_value = *first; + typename Container::node_type t = c.extract(first++); + --sz; + assert(t.value() == key_value); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); +} + +int main() +{ + { + using set_type = std::unordered_set; + set_type m = {1, 2, 3, 4, 5, 6}; + test(m); + } + + { + std::unordered_set> m = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 6); + test(m); + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_set = std::unordered_set, std::equal_to, min_allocator>; + min_alloc_set m = {1, 2, 3, 4, 5, 6}; + test(m); + } +} diff --git a/test/std/containers/unord/unord.set/extract_key.pass.cpp b/test/std/containers/unord/unord.set/extract_key.pass.cpp new file mode 100644 index 000000000..f686342b2 --- /dev/null +++ b/test/std/containers/unord/unord.set/extract_key.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_set + +// node_type extract(key_type const&); + +#include +#include "min_allocator.h" +#include "Counter.h" + +template +void test(Container& c, KeyTypeIter first, KeyTypeIter last) +{ + size_t sz = c.size(); + assert((size_t)std::distance(first, last) == sz); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(!t.empty()); + --sz; + assert(t.value() == *copy); + assert(t.get_allocator() == c.get_allocator()); + assert(sz == c.size()); + } + + assert(c.size() == 0); + + for (KeyTypeIter copy = first; copy != last; ++copy) + { + typename Container::node_type t = c.extract(*copy); + assert(t.empty()); + } +} + +int main() +{ + { + std::unordered_set m = {1, 2, 3, 4, 5, 6}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } + + { + std::unordered_set> m = {1, 2, 3, 4, 5, 6}; + { + Counter keys[] = {1, 2, 3, 4, 5, 6}; + assert(Counter_base::gConstructed == 6+6); + test(m, std::begin(keys), std::end(keys)); + } + assert(Counter_base::gConstructed == 0); + } + + { + using min_alloc_set = std::unordered_set, std::equal_to, min_allocator>; + min_alloc_set m = {1, 2, 3, 4, 5, 6}; + int keys[] = {1, 2, 3, 4, 5, 6}; + test(m, std::begin(keys), std::end(keys)); + } +} diff --git a/test/std/containers/unord/unord.set/insert_node_type.pass.cpp b/test/std/containers/unord/unord.set/insert_node_type.pass.cpp new file mode 100644 index 000000000..6c91b5393 --- /dev/null +++ b/test/std/containers/unord/unord.set/insert_node_type.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_set + +// insert_return_type insert(node_type&&); + +#include +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key) +{ + static Container c; + auto p = c.insert(key); + assert(p.second); + return c.extract(p.first); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i); + assert(!node.empty()); + typename Container::insert_return_type irt = c.insert(std::move(node)); + assert(node.empty()); + assert(irt.inserted); + assert(irt.node.empty()); + assert(*irt.position == i); + } + + assert(c.size() == 10); + + { // Insert empty node. + typename Container::node_type def; + auto irt = c.insert(std::move(def)); + assert(def.empty()); + assert(!irt.inserted); + assert(irt.node.empty()); + assert(irt.position == c.end()); + } + + { // Insert duplicate node. + typename Container::node_type dupl = nf(0); + auto irt = c.insert(std::move(dupl)); + assert(dupl.empty()); + assert(!irt.inserted); + assert(!irt.node.empty()); + assert(irt.position == c.find(0)); + assert(irt.node.value() == 0); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + } +} + +int main() +{ + std::unordered_set m; + test(m); + std::unordered_set, std::equal_to, min_allocator> m2; + test(m2); +} diff --git a/test/std/containers/unord/unord.set/insert_node_type_hint.pass.cpp b/test/std/containers/unord/unord.set/insert_node_type_hint.pass.cpp new file mode 100644 index 000000000..626f27271 --- /dev/null +++ b/test/std/containers/unord/unord.set/insert_node_type_hint.pass.cpp @@ -0,0 +1,61 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// class unordered_set + +// iterator insert(const_iterator hint, node_type&&); + +#include +#include "min_allocator.h" + +template +typename Container::node_type +node_factory(typename Container::key_type const& key) +{ + static Container c; + auto p = c.insert(key); + assert(p.second); + return c.extract(p.first); +} + +template +void test(Container& c) +{ + auto* nf = &node_factory; + + for (int i = 0; i != 10; ++i) + { + typename Container::node_type node = nf(i); + assert(!node.empty()); + size_t prev = c.size(); + auto it = c.insert(c.end(), std::move(node)); + assert(node.empty()); + assert(prev + 1 == c.size()); + assert(*it == i); + } + + assert(c.size() == 10); + + for (int i = 0; i != 10; ++i) + { + assert(c.count(i) == 1); + } +} + +int main() +{ + std::unordered_set m; + test(m); + std::unordered_set, std::equal_to, min_allocator> m2; + test(m2); +} diff --git a/test/support/Counter.h b/test/support/Counter.h index 4a658c58c..63ed60801 100644 --- a/test/support/Counter.h +++ b/test/support/Counter.h @@ -23,7 +23,7 @@ public: Counter() : data_() { ++gConstructed; } Counter(const T &data) : data_(data) { ++gConstructed; } Counter(const Counter& rhs) : data_(rhs.data_) { ++gConstructed; } - Counter& operator=(const Counter& rhs) { ++gConstructed; data_ = rhs.data_; return *this; } + Counter& operator=(const Counter& rhs) { data_ = rhs.data_; return *this; } #if TEST_STD_VER >= 11 Counter(Counter&& rhs) : data_(std::move(rhs.data_)) { ++gConstructed; } Counter& operator=(Counter&& rhs) { ++gConstructed; data_ = std::move(rhs.data_); return *this; } @@ -49,7 +49,7 @@ struct hash > typedef Counter argument_type; typedef std::size_t result_type; - std::size_t operator()(const Counter& x) const {return std::hash(x.get());} + std::size_t operator()(const Counter& x) const {return std::hash()(x.get());} }; } -- GitLab From 6952d1478ddd5a1870079d01f1a0e1eea5b09a1a Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 1 Aug 2018 02:08:59 +0000 Subject: [PATCH 118/495] [libc++] Remove _LIBCPP_BUILDING_XXX macros, which are redundant since _LIBCPP_BUILDING_LIBRARY Summary: As suggested by Marshall in https://reviews.llvm.org/D49914 Reviewers: mclow.lists, EricWF Subscribers: christof, dexonsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D50008 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338475 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/__functional_base | 2 +- include/__mutex_base | 2 +- include/functional | 4 ++-- include/memory | 6 +++--- include/new | 6 +++--- include/shared_mutex | 2 +- include/system_error | 2 +- include/utility | 2 +- src/bind.cpp | 1 - src/memory.cpp | 1 - src/mutex.cpp | 1 - src/new.cpp | 2 -- src/shared_mutex.cpp | 1 - src/system_error.cpp | 1 - src/utility.cpp | 1 - 15 files changed, 13 insertions(+), 21 deletions(-) diff --git a/include/__functional_base b/include/__functional_base index 1a90bd628..57fdf2b9f 100644 --- a/include/__functional_base +++ b/include/__functional_base @@ -561,7 +561,7 @@ struct __is_transparent<_Tp, _Up, struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { }; -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_MEMORY) +#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) extern const allocator_arg_t allocator_arg; #else /* _LIBCPP_INLINE_VAR */ constexpr allocator_arg_t allocator_arg = allocator_arg_t(); diff --git a/include/__mutex_base b/include/__mutex_base index 402a52d94..4659ca929 100644 --- a/include/__mutex_base +++ b/include/__mutex_base @@ -74,7 +74,7 @@ struct _LIBCPP_TYPE_VIS defer_lock_t {}; struct _LIBCPP_TYPE_VIS try_to_lock_t {}; struct _LIBCPP_TYPE_VIS adopt_lock_t {}; -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_MUTEX) +#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; diff --git a/include/functional b/include/functional index 80261895e..6b70f731e 100644 --- a/include/functional +++ b/include/functional @@ -2005,7 +2005,7 @@ namespace placeholders template struct __ph {}; -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_BIND) +#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) _LIBCPP_FUNC_VIS extern const __ph<1> _1; _LIBCPP_FUNC_VIS extern const __ph<2> _2; _LIBCPP_FUNC_VIS extern const __ph<3> _3; @@ -2027,7 +2027,7 @@ _LIBCPP_FUNC_VIS extern const __ph<10> _10; /* _LIBCPP_INLINE_VAR */ constexpr __ph<8> _8{}; /* _LIBCPP_INLINE_VAR */ constexpr __ph<9> _9{}; /* _LIBCPP_INLINE_VAR */ constexpr __ph<10> _10{}; -#endif // defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_BIND) +#endif // defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) } // placeholders diff --git a/include/memory b/include/memory index fd830d7ed..a4bf89b49 100644 --- a/include/memory +++ b/include/memory @@ -3511,7 +3511,7 @@ public: explicit __shared_count(long __refs = 0) _NOEXCEPT : __shared_owners_(__refs) {} -#if defined(_LIBCPP_BUILDING_MEMORY) && \ +#if defined(_LIBCPP_BUILDING_LIBRARY) && \ defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) void __add_shared() _NOEXCEPT; bool __release_shared() _NOEXCEPT; @@ -3549,7 +3549,7 @@ protected: virtual ~__shared_weak_count(); public: -#if defined(_LIBCPP_BUILDING_MEMORY) && \ +#if defined(_LIBCPP_BUILDING_LIBRARY) && \ defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) void __add_shared() _NOEXCEPT; void __add_weak() _NOEXCEPT; @@ -5549,7 +5549,7 @@ struct _LIBCPP_TYPE_VIS pointer_safety #endif #if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE) && \ - defined(_LIBCPP_BUILDING_MEMORY) + defined(_LIBCPP_BUILDING_LIBRARY) _LIBCPP_FUNC_VIS pointer_safety get_pointer_safety() _NOEXCEPT; #else // This function is only offered in C++03 under ABI v1. diff --git a/include/new b/include/new index b5dc05542..e70b9c621 100644 --- a/include/new +++ b/include/new @@ -103,13 +103,13 @@ void operator delete[](void* ptr, void*) noexcept; #pragma GCC system_header #endif -#if !(defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER >= 14 || \ +#if !(defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_STD_VER >= 14 || \ (defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309)) # define _LIBCPP_HAS_NO_SIZED_DEALLOCATION #endif #if !defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) && \ - (!(defined(_LIBCPP_BUILDING_NEW) || _LIBCPP_STD_VER > 14 || \ + (!(defined(_LIBCPP_BUILDING_LIBRARY) || _LIBCPP_STD_VER > 14 || \ (defined(__cpp_aligned_new) && __cpp_aligned_new >= 201606))) # define _LIBCPP_HAS_NO_ALIGNED_ALLOCATION #endif @@ -167,7 +167,7 @@ public: #define _LIBCPP_BAD_ARRAY_LENGTH_DEFINED -#endif // defined(_LIBCPP_BUILDING_NEW) || (_LIBCPP_STD_VER > 11) +#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 diff --git a/include/shared_mutex b/include/shared_mutex index 9cb81528c..a7735d673 100644 --- a/include/shared_mutex +++ b/include/shared_mutex @@ -129,7 +129,7 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> -#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_SHARED_MUTEX) +#if _LIBCPP_STD_VER > 11 || defined(_LIBCPP_BUILDING_LIBRARY) #include <__mutex_base> diff --git a/include/system_error b/include/system_error index 917c71029..6e2c8388f 100644 --- a/include/system_error +++ b/include/system_error @@ -199,7 +199,7 @@ class _LIBCPP_TYPE_VIS error_category public: virtual ~error_category() _NOEXCEPT; -#if defined(_LIBCPP_BUILDING_SYSTEM_ERROR) && \ +#if defined(_LIBCPP_BUILDING_LIBRARY) && \ defined(_LIBCPP_DEPRECATED_ABI_LEGACY_LIBRARY_DEFINITIONS_FOR_INLINE_FUNCTIONS) error_category() _NOEXCEPT; #else diff --git a/include/utility b/include/utility index 8fdaf65db..ed9bf030d 100644 --- a/include/utility +++ b/include/utility @@ -295,7 +295,7 @@ template void as_const(const _Tp&&) = delete; #endif struct _LIBCPP_TEMPLATE_VIS piecewise_construct_t { }; -#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_UTILITY) +#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY) extern const piecewise_construct_t piecewise_construct;// = piecewise_construct_t(); #else /* _LIBCPP_INLINE_VAR */ constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); diff --git a/src/bind.cpp b/src/bind.cpp index b318fc169..b4c76ffe6 100644 --- a/src/bind.cpp +++ b/src/bind.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#define _LIBCPP_BUILDING_BIND #include "functional" _LIBCPP_BEGIN_NAMESPACE_STD diff --git a/src/memory.cpp b/src/memory.cpp index 4e0d3af91..77ebe837c 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#define _LIBCPP_BUILDING_MEMORY #include "memory" #ifndef _LIBCPP_HAS_NO_THREADS #include "mutex" diff --git a/src/mutex.cpp b/src/mutex.cpp index c36bd5549..c61d34bb8 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#define _LIBCPP_BUILDING_MUTEX #include "mutex" #include "limits" #include "system_error" diff --git a/src/new.cpp b/src/new.cpp index e228a0d83..8013d89ae 100644 --- a/src/new.cpp +++ b/src/new.cpp @@ -7,8 +7,6 @@ // //===----------------------------------------------------------------------===// -#define _LIBCPP_BUILDING_NEW - #include #include "new" diff --git a/src/shared_mutex.cpp b/src/shared_mutex.cpp index 874aceb1b..6185f15de 100644 --- a/src/shared_mutex.cpp +++ b/src/shared_mutex.cpp @@ -10,7 +10,6 @@ #include "__config" #ifndef _LIBCPP_HAS_NO_THREADS -#define _LIBCPP_BUILDING_SHARED_MUTEX #include "shared_mutex" _LIBCPP_BEGIN_NAMESPACE_STD diff --git a/src/system_error.cpp b/src/system_error.cpp index 72623ea6b..06caa6fec 100644 --- a/src/system_error.cpp +++ b/src/system_error.cpp @@ -9,7 +9,6 @@ #include "__config" -#define _LIBCPP_BUILDING_SYSTEM_ERROR #include "system_error" #include "include/config_elast.h" diff --git a/src/utility.cpp b/src/utility.cpp index e9830e7c2..7dccffb73 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#define _LIBCPP_BUILDING_UTILITY #include "utility" _LIBCPP_BEGIN_NAMESPACE_STD -- GitLab From dc38e97601dd5b8c4a9a520c11a03698242d916b Mon Sep 17 00:00:00 2001 From: Zhihao Yuan Date: Wed, 1 Aug 2018 02:38:30 +0000 Subject: [PATCH 119/495] [libc++][C++17] Elementary string conversions for integral types Summary: Major QoI considerations: - The facility is backported to C++14, same as libstdc++. - Efforts have been made to minimize the header dependencies. - The design is friendly to the uses of MSVC intrinsics (`__emulu`, `_umul128`, `_BitScanForward`, `_BitScanForward64`) but not implemented; future contributions are welcome. Thanks to Milo Yip for contributing the implementation of `__u64toa` and `__u32toa`. References: https://wg21.link/p0067r5 https://wg21.link/p0682r1 Reviewers: mclow.lists, EricWF Reviewed By: mclow.lists Subscribers: ldionne, Quuxplusone, christof, mgorny, cfe-commits Differential Revision: https://reviews.llvm.org/D41458 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@338479 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/CMakeLists.txt | 1 + include/charconv | 610 ++++++++++++++++++ include/module.modulemap | 4 + src/charconv.cpp | 233 +++++++ test/libcxx/double_include.sh.cpp | 1 + .../integral.bool.fail.cpp | 30 + .../charconv.from.chars/integral.pass.cpp | 181 ++++++ .../charconv.to.chars/integral.bool.fail.cpp | 30 + .../charconv.to.chars/integral.pass.cpp | 80 +++ test/support/charconv_test_helpers.h | 232 +++++++ 10 files changed, 1402 insertions(+) create mode 100644 include/charconv create mode 100644 src/charconv.cpp create mode 100644 test/std/utilities/charconv/charconv.from.chars/integral.bool.fail.cpp create mode 100644 test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp create mode 100644 test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp create mode 100644 test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp create mode 100644 test/support/charconv_test_helpers.h diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index a45b80160..d9def18d7 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -32,6 +32,7 @@ set(files cerrno cfenv cfloat + charconv chrono cinttypes ciso646 diff --git a/include/charconv b/include/charconv new file mode 100644 index 000000000..7cb790e1b --- /dev/null +++ b/include/charconv @@ -0,0 +1,610 @@ +// -*- C++ -*- +//===------------------------------ charconv ------------------------------===// +// +// 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_CHARCONV +#define _LIBCPP_CHARCONV + +/* + charconv synopsis + +namespace std { + + // floating-point format for primitive numerical conversion + enum class chars_format { + scientific = unspecified, + fixed = unspecified, + hex = unspecified, + general = fixed | scientific + }; + + // 23.20.2, primitive numerical output conversion + struct to_chars_result { + char* ptr; + errc ec; + }; + + to_chars_result to_chars(char* first, char* last, see below value, + int base = 10); + + to_chars_result to_chars(char* first, char* last, float value); + to_chars_result to_chars(char* first, char* last, double value); + to_chars_result to_chars(char* first, char* last, long double value); + + to_chars_result to_chars(char* first, char* last, float value, + chars_format fmt); + to_chars_result to_chars(char* first, char* last, double value, + chars_format fmt); + to_chars_result to_chars(char* first, char* last, long double value, + chars_format fmt); + + to_chars_result to_chars(char* first, char* last, float value, + chars_format fmt, int precision); + to_chars_result to_chars(char* first, char* last, double value, + chars_format fmt, int precision); + to_chars_result to_chars(char* first, char* last, long double value, + chars_format fmt, int precision); + + // 23.20.3, primitive numerical input conversion + struct from_chars_result { + const char* ptr; + errc ec; + }; + + from_chars_result from_chars(const char* first, const char* last, + see below& value, int base = 10); + + from_chars_result from_chars(const char* first, const char* last, + float& value, + chars_format fmt = chars_format::general); + from_chars_result from_chars(const char* first, const char* last, + double& value, + chars_format fmt = chars_format::general); + from_chars_result from_chars(const char* first, const char* last, + long double& value, + chars_format fmt = chars_format::general); + +} // namespace std + +*/ + +#include <__errc> +#include +#include +#include +#include +#include + +#include <__debug> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 11 + +enum class _LIBCPP_ENUM_VIS chars_format +{ + scientific = 0x1, + fixed = 0x2, + hex = 0x4, + general = fixed | scientific +}; + +struct _LIBCPP_TYPE_VIS to_chars_result +{ + char* ptr; + errc ec; +}; + +struct _LIBCPP_TYPE_VIS from_chars_result +{ + const char* ptr; + errc ec; +}; + +void to_chars(char*, char*, bool, int = 10) = delete; +void from_chars(const char*, const char*, bool, int = 10) = delete; + +namespace __itoa +{ + +static constexpr uint64_t __pow10_64[] = { + UINT64_C(0), + UINT64_C(10), + UINT64_C(100), + UINT64_C(1000), + UINT64_C(10000), + UINT64_C(100000), + UINT64_C(1000000), + UINT64_C(10000000), + UINT64_C(100000000), + UINT64_C(1000000000), + UINT64_C(10000000000), + UINT64_C(100000000000), + UINT64_C(1000000000000), + UINT64_C(10000000000000), + UINT64_C(100000000000000), + UINT64_C(1000000000000000), + UINT64_C(10000000000000000), + UINT64_C(100000000000000000), + UINT64_C(1000000000000000000), + UINT64_C(10000000000000000000), +}; + +static constexpr uint32_t __pow10_32[] = { + UINT32_C(0), UINT32_C(10), UINT32_C(100), + UINT32_C(1000), UINT32_C(10000), UINT32_C(100000), + UINT32_C(1000000), UINT32_C(10000000), UINT32_C(100000000), + UINT32_C(1000000000), +}; + +_LIBCPP_FUNC_VIS char* __u64toa(uint64_t __value, char* __buffer); +_LIBCPP_FUNC_VIS char* __u32toa(uint32_t __value, char* __buffer); + +template +struct _LIBCPP_HIDDEN __traits_base +{ + using type = uint64_t; + +#if !defined(_LIBCPP_COMPILER_MSVC) + static _LIBCPP_INLINE_VISIBILITY int __width(_Tp __v) + { + auto __t = (64 - __builtin_clzll(__v | 1)) * 1233 >> 12; + return __t - (__v < __pow10_64[__t]) + 1; + } +#endif + + static _LIBCPP_INLINE_VISIBILITY char* __convert(_Tp __v, char* __p) + { + return __u64toa(__v, __p); + } + + static _LIBCPP_INLINE_VISIBILITY auto& __pow() { return __pow10_64; } +}; + +template +struct _LIBCPP_HIDDEN + __traits_base<_Tp, decltype(void(uint32_t{declval<_Tp>()}))> +{ + using type = uint32_t; + +#if !defined(_LIBCPP_COMPILER_MSVC) + static _LIBCPP_INLINE_VISIBILITY int __width(_Tp __v) + { + auto __t = (32 - __builtin_clz(__v | 1)) * 1233 >> 12; + return __t - (__v < __pow10_32[__t]) + 1; + } +#endif + + static _LIBCPP_INLINE_VISIBILITY char* __convert(_Tp __v, char* __p) + { + return __u32toa(__v, __p); + } + + static _LIBCPP_INLINE_VISIBILITY auto& __pow() { return __pow10_32; } +}; + +template +inline _LIBCPP_INLINE_VISIBILITY bool +__mul_overflowed(unsigned char __a, _Tp __b, unsigned char& __r) +{ + auto __c = __a * __b; + __r = __c; + return __c > (numeric_limits::max)(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY bool +__mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) +{ + auto __c = __a * __b; + __r = __c; + return __c > (numeric_limits::max)(); +} + +template +inline _LIBCPP_INLINE_VISIBILITY bool +__mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) +{ + static_assert(is_unsigned<_Tp>::value, ""); +#if !defined(_LIBCPP_COMPILER_MSVC) + return __builtin_mul_overflow(__a, __b, &__r); +#else + bool __did = __b && ((numeric_limits<_Tp>::max)() / __b) < __a; + __r = __a * __b; + return __did; +#endif +} + +template +inline _LIBCPP_INLINE_VISIBILITY bool +__mul_overflowed(_Tp __a, _Up __b, _Tp& __r) +{ + return __mul_overflowed(__a, static_cast<_Tp>(__b), __r); +} + +template +struct _LIBCPP_HIDDEN __traits : __traits_base<_Tp> +{ + static constexpr int digits = numeric_limits<_Tp>::digits10 + 1; + using __traits_base<_Tp>::__pow; + using typename __traits_base<_Tp>::type; + + // precondition: at least one non-zero character available + static _LIBCPP_INLINE_VISIBILITY char const* + __read(char const* __p, char const* __ep, type& __a, type& __b) + { + type __cprod[digits]; + int __j = digits - 1; + int __i = digits; + do + { + if (!('0' <= *__p && *__p <= '9')) + break; + __cprod[--__i] = *__p++ - '0'; + } while (__p != __ep && __i != 0); + + __a = __inner_product(__cprod + __i + 1, __cprod + __j, __pow() + 1, + __cprod[__i]); + if (__mul_overflowed(__cprod[__j], __pow()[__j - __i], __b)) + --__p; + return __p; + } + + template + static _LIBCPP_INLINE_VISIBILITY _Up + __inner_product(_It1 __first1, _It1 __last1, _It2 __first2, _Up __init) + { + for (; __first1 < __last1; ++__first1, ++__first2) + __init = __init + *__first1 * *__first2; + return __init; + } +}; + +} // namespace __itoa + +template +inline _LIBCPP_INLINE_VISIBILITY _Tp +__complement(_Tp __x) +{ + static_assert(is_unsigned<_Tp>::value, "cast to unsigned first"); + return _Tp(~__x + 1); +} + +template +inline _LIBCPP_INLINE_VISIBILITY auto +__to_unsigned(_Tp __x) +{ + return static_cast>(__x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY to_chars_result +__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) +{ + auto __x = __to_unsigned(__value); + if (__value < 0 && __first != __last) + { + *__first++ = '-'; + __x = __complement(__x); + } + + return __to_chars_itoa(__first, __last, __x, false_type()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY to_chars_result +__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) +{ + using __tx = __itoa::__traits<_Tp>; + auto __diff = __last - __first; + +#if !defined(_LIBCPP_COMPILER_MSVC) + if (__tx::digits <= __diff || __tx::__width(__value) <= __diff) + return {__tx::__convert(__value, __first), {}}; + else + return {__last, errc::value_too_large}; +#else + if (__tx::digits <= __diff) + return {__tx::__convert(__value, __first), {}}; + else + { + char __buf[__tx::digits]; + auto __p = __tx::__convert(__value, __buf); + auto __len = __p - __buf; + if (__len <= __diff) + { + memcpy(__first, __buf, __len); + return {__first + __len, {}}; + } + else + return {__last, errc::value_too_large}; + } +#endif +} + +template +inline _LIBCPP_INLINE_VISIBILITY to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, + true_type) +{ + auto __x = __to_unsigned(__value); + if (__value < 0 && __first != __last) + { + *__first++ = '-'; + __x = __complement(__x); + } + + return __to_chars_integral(__first, __last, __x, __base, false_type()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY to_chars_result +__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, + false_type) +{ + if (__base == 10) + return __to_chars_itoa(__first, __last, __value, false_type()); + + auto __p = __last; + while (__p != __first) + { + auto __c = __value % __base; + __value /= __base; + *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c]; + if (__value == 0) + break; + } + + auto __len = __last - __p; + if (__value != 0 || !__len) + return {__last, errc::value_too_large}; + else + { + memmove(__first, __p, __len); + return {__first + __len, {}}; + } +} + +template ::value, int> = 0> +inline _LIBCPP_INLINE_VISIBILITY to_chars_result +to_chars(char* __first, char* __last, _Tp __value) +{ + return __to_chars_itoa(__first, __last, __value, is_signed<_Tp>()); +} + +template ::value, int> = 0> +inline _LIBCPP_INLINE_VISIBILITY to_chars_result +to_chars(char* __first, char* __last, _Tp __value, int __base) +{ + _LIBCPP_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]"); + return __to_chars_integral(__first, __last, __value, __base, + is_signed<_Tp>()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY from_chars_result +__sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) +{ + using __tl = numeric_limits<_Tp>; + decltype(__to_unsigned(__value)) __x; + + bool __neg = (__first != __last && *__first == '-'); + auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...); + switch (__r.ec) + { + case errc::invalid_argument: + return {__first, __r.ec}; + case errc::result_out_of_range: + return __r; + default: + break; + } + + if (__neg) + { + if (__x <= __complement(__to_unsigned(__tl::min()))) + { + __x = __complement(__x); + memcpy(&__value, &__x, sizeof(__x)); + return __r; + } + } + else + { + if (__x <= (__tl::max)()) + { + __value = __x; + return __r; + } + } + + return {__r.ptr, errc::result_out_of_range}; +} + +template +inline _LIBCPP_INLINE_VISIBILITY bool +__in_pattern(_Tp __c) +{ + return '0' <= __c && __c <= '9'; +} + +struct _LIBCPP_HIDDEN __in_pattern_result +{ + bool __ok; + int __val; + + explicit _LIBCPP_INLINE_VISIBILITY operator bool() const { return __ok; } +}; + +template +inline _LIBCPP_INLINE_VISIBILITY __in_pattern_result +__in_pattern(_Tp __c, int __base) +{ + if (__base <= 10) + return {'0' <= __c && __c < '0' + __base, __c - '0'}; + else if (__in_pattern(__c)) + return {true, __c - '0'}; + else if ('a' <= __c && __c < 'a' + __base - 10) + return {true, __c - 'a' + 10}; + else + return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10}; +} + +template +inline _LIBCPP_INLINE_VISIBILITY from_chars_result +__subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, + _Ts... __args) +{ + auto __find_non_zero = [](_It __first, _It __last) { + for (; __first != __last; ++__first) + if (*__first != '0') + break; + return __first; + }; + + auto __p = __find_non_zero(__first, __last); + if (__p == __last || !__in_pattern(*__p, __args...)) + { + if (__p == __first) + return {__first, errc::invalid_argument}; + else + { + __value = 0; + return {__p, {}}; + } + } + + auto __r = __f(__p, __last, __value, __args...); + if (__r.ec == errc::result_out_of_range) + { + for (; __r.ptr != __last; ++__r.ptr) + { + if (!__in_pattern(*__r.ptr, __args...)) + break; + } + } + + return __r; +} + +template ::value, int> = 0> +inline _LIBCPP_INLINE_VISIBILITY from_chars_result +__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) +{ + using __tx = __itoa::__traits<_Tp>; + using __output_type = typename __tx::type; + + return __subject_seq_combinator( + __first, __last, __value, + [](const char* __first, const char* __last, + _Tp& __value) -> from_chars_result { + __output_type __a, __b; + auto __p = __tx::__read(__first, __last, __a, __b); + if (__p == __last || !__in_pattern(*__p)) + { + __output_type __m = (numeric_limits<_Tp>::max)(); + if (__m >= __a && __m - __a >= __b) + { + __value = __a + __b; + return {__p, {}}; + } + } + return {__p, errc::result_out_of_range}; + }); +} + +template ::value, int> = 0> +inline _LIBCPP_INLINE_VISIBILITY from_chars_result +__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) +{ + using __t = decltype(__to_unsigned(__value)); + return __sign_combinator(__first, __last, __value, __from_chars_atoi<__t>); +} + +template ::value, int> = 0> +inline _LIBCPP_INLINE_VISIBILITY from_chars_result +__from_chars_integral(const char* __first, const char* __last, _Tp& __value, + int __base) +{ + if (__base == 10) + return __from_chars_atoi(__first, __last, __value); + + return __subject_seq_combinator( + __first, __last, __value, + [](const char* __p, const char* __last, _Tp& __value, + int __base) -> from_chars_result { + using __tl = numeric_limits<_Tp>; + auto __digits = __tl::digits / log2f(float(__base)); + _Tp __a = __in_pattern(*__p++, __base).__val, __b = 0; + + for (int __i = 1; __p != __last; ++__i, ++__p) + { + if (auto __c = __in_pattern(*__p, __base)) + { + if (__i < __digits - 1) + __a = __a * __base + __c.__val; + else + { + if (!__itoa::__mul_overflowed(__a, __base, __a)) + ++__p; + __b = __c.__val; + break; + } + } + else + break; + } + + if (__p == __last || !__in_pattern(*__p, __base)) + { + if ((__tl::max)() - __a >= __b) + { + __value = __a + __b; + return {__p, {}}; + } + } + return {__p, errc::result_out_of_range}; + }, + __base); +} + +template ::value, int> = 0> +inline _LIBCPP_INLINE_VISIBILITY from_chars_result +__from_chars_integral(const char* __first, const char* __last, _Tp& __value, + int __base) +{ + using __t = decltype(__to_unsigned(__value)); + return __sign_combinator(__first, __last, __value, + __from_chars_integral<__t>, __base); +} + +template ::value, int> = 0> +inline _LIBCPP_INLINE_VISIBILITY from_chars_result +from_chars(const char* __first, const char* __last, _Tp& __value) +{ + return __from_chars_atoi(__first, __last, __value); +} + +template ::value, int> = 0> +inline _LIBCPP_INLINE_VISIBILITY from_chars_result +from_chars(const char* __first, const char* __last, _Tp& __value, int __base) +{ + _LIBCPP_ASSERT(2 <= __base && __base <= 36, "base not in [2, 36]"); + return __from_chars_integral(__first, __last, __value, __base); +} + +#endif // _LIBCPP_STD_VER > 11 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_CHARCONV diff --git a/include/module.modulemap b/include/module.modulemap index 3b66390fb..089505586 100644 --- a/include/module.modulemap +++ b/include/module.modulemap @@ -235,6 +235,10 @@ module std [system] { export * } // No submodule for cassert. It fundamentally needs repeated, textual inclusion. + module charconv { + header "charconv" + export * + } module chrono { header "chrono" export * diff --git a/src/charconv.cpp b/src/charconv.cpp new file mode 100644 index 000000000..ec241db74 --- /dev/null +++ b/src/charconv.cpp @@ -0,0 +1,233 @@ +//===------------------------- charconv.cpp -------------------------------===// +// +// 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 "charconv" +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __itoa +{ + +static constexpr char cDigitsLut[200] = { + '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', + '7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', + '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2', + '2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', + '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', + '7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', + '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5', + '2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', + '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6', + '7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', + '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8', + '2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', + '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9', + '7', '9', '8', '9', '9'}; + +template +inline _LIBCPP_INLINE_VISIBILITY char* +append1(char* buffer, T i) +{ + *buffer = '0' + static_cast(i); + return buffer + 1; +} + +template +inline _LIBCPP_INLINE_VISIBILITY char* +append2(char* buffer, T i) +{ + memcpy(buffer, &cDigitsLut[(i)*2], 2); + return buffer + 2; +} + +template +inline _LIBCPP_INLINE_VISIBILITY char* +append3(char* buffer, T i) +{ + return append2(append1(buffer, (i) / 100), (i) % 100); +} + +template +inline _LIBCPP_INLINE_VISIBILITY char* +append4(char* buffer, T i) +{ + return append2(append2(buffer, (i) / 100), (i) % 100); +} + +char* +__u32toa(uint32_t value, char* buffer) +{ + if (value < 10000) + { + if (value < 100) + { + if (value < 10) + buffer = append1(buffer, value); + else + buffer = append2(buffer, value); + } + else + { + if (value < 1000) + buffer = append3(buffer, value); + else + buffer = append4(buffer, value); + } + } + else if (value < 100000000) + { + // value = bbbbcccc + const uint32_t b = value / 10000; + const uint32_t c = value % 10000; + + if (value < 1000000) + { + if (value < 100000) + buffer = append1(buffer, b); + else + buffer = append2(buffer, b); + } + else + { + if (value < 10000000) + buffer = append3(buffer, b); + else + buffer = append4(buffer, b); + } + + buffer = append4(buffer, c); + } + else + { + // value = aabbbbcccc in decimal + const uint32_t a = value / 100000000; // 1 to 42 + value %= 100000000; + + if (a < 10) + buffer = append1(buffer, a); + else + buffer = append2(buffer, a); + + buffer = append4(buffer, value / 10000); + buffer = append4(buffer, value % 10000); + } + + return buffer; +} + +char* +__u64toa(uint64_t value, char* buffer) +{ + if (value < 100000000) + { + uint32_t v = static_cast(value); + if (v < 10000) + { + if (v < 100) + { + if (v < 10) + buffer = append1(buffer, v); + else + buffer = append2(buffer, v); + } + else + { + if (v < 1000) + buffer = append3(buffer, v); + else + buffer = append4(buffer, v); + } + } + else + { + // value = bbbbcccc + const uint32_t b = v / 10000; + const uint32_t c = v % 10000; + + if (v < 1000000) + { + if (v < 100000) + buffer = append1(buffer, b); + else + buffer = append2(buffer, b); + } + else + { + if (v < 10000000) + buffer = append3(buffer, b); + else + buffer = append4(buffer, b); + } + + buffer = append4(buffer, c); + } + } + else if (value < 10000000000000000) + { + const uint32_t v0 = static_cast(value / 100000000); + const uint32_t v1 = static_cast(value % 100000000); + + const uint32_t b0 = v0 / 10000; + const uint32_t c0 = v0 % 10000; + + if (v0 < 1000000) + { + if (v0 < 100000) + buffer = append1(buffer, b0); + else + buffer = append2(buffer, b0); + } + else + { + if (v0 < 10000000) + buffer = append3(buffer, b0); + else + buffer = append4(buffer, b0); + } + + buffer = append4(buffer, c0); + buffer = append4(buffer, v1 / 10000); + buffer = append4(buffer, v1 % 10000); + } + else + { + const uint32_t a = + static_cast(value / 10000000000000000); // 1 to 1844 + value %= 10000000000000000; + + if (a < 100) + { + if (a < 10) + buffer = append1(buffer, a); + else + buffer = append2(buffer, a); + } + else + { + if (a < 1000) + buffer = append3(buffer, a); + else + buffer = append4(buffer, a); + } + + const uint32_t v0 = static_cast(value / 100000000); + const uint32_t v1 = static_cast(value % 100000000); + buffer = append4(buffer, v0 / 10000); + buffer = append4(buffer, v0 % 10000); + buffer = append4(buffer, v1 / 10000); + buffer = append4(buffer, v1 % 10000); + } + + return buffer; +} + +} // namespace __itoa + +_LIBCPP_END_NAMESPACE_STD diff --git a/test/libcxx/double_include.sh.cpp b/test/libcxx/double_include.sh.cpp index c98cc8065..8d08db4fd 100644 --- a/test/libcxx/double_include.sh.cpp +++ b/test/libcxx/double_include.sh.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include diff --git a/test/std/utilities/charconv/charconv.from.chars/integral.bool.fail.cpp b/test/std/utilities/charconv/charconv.from.chars/integral.bool.fail.cpp new file mode 100644 index 000000000..d21b638d0 --- /dev/null +++ b/test/std/utilities/charconv/charconv.from.chars/integral.bool.fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// + +// In +// +// from_chars_result from_chars(const char* first, const char* last, +// Integral& value, int base = 10) +// +// Integral cannot be bool. + +#include + +int main() +{ + using std::from_chars; + char buf[] = "01001"; + bool lv; + + from_chars(buf, buf + sizeof(buf), lv); // expected-error {{call to deleted function}} + from_chars(buf, buf + sizeof(buf), lv, 16); // expected-error {{call to deleted function}} +} diff --git a/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp b/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp new file mode 100644 index 000000000..e5a93b497 --- /dev/null +++ b/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp @@ -0,0 +1,181 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// + +// from_chars_result from_chars(const char* first, const char* last, +// Integral& value, int base = 10) + +#include "charconv_test_helpers.h" + +template +struct test_basics : roundtrip_test_base +{ + using roundtrip_test_base::test; + + void operator()() + { + test(0); + test(42); + test(32768); + test(0, 10); + test(42, 10); + test(32768, 10); + test(0xf, 16); + test(0xdeadbeaf, 16); + test(0755, 8); + + for (int b = 2; b < 37; ++b) + { + using xl = std::numeric_limits; + + test(1, b); + test(xl::lowest(), b); + test((xl::max)(), b); + test((xl::max)() / 2, b); + } + + using std::from_chars; + std::from_chars_result r; + T x; + + { + char s[] = "001x"; + + // the expected form of the subject sequence is a sequence of + // letters and digits representing an integer with the radix + // specified by base (C11 7.22.1.4/3) + r = from_chars(s, s + sizeof(s), x); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 3); + assert(x == 1); + } + + { + char s[] = "0X7BAtSGHDkEIXZg "; + + // The letters from a (or A) through z (or Z) are ascribed the + // values 10 through 35; (C11 7.22.1.4/3) + r = from_chars(s, s + sizeof(s), x, 36); + assert(r.ec == std::errc::result_out_of_range); + // The member ptr of the return value points to the first character + // not matching the pattern + assert(r.ptr == s + sizeof(s) - 2); + assert(x == 1); + + // no "0x" or "0X" prefix shall appear if the value of base is 16 + r = from_chars(s, s + sizeof(s), x, 16); + assert(r.ec == std::errc{}); + assert(r.ptr == s + 1); + assert(x == 0); + + // only letters and digits whose ascribed values are less than that + // of base are permitted. (C11 7.22.1.4/3) + r = from_chars(s + 2, s + sizeof(s), x, 12); + // If the parsed value is not in the range representable by the type + // of value, + if (!fits_in(1150)) + { + // value is unmodified and + assert(x == 0); + // the member ec of the return value is equal to + // errc::result_out_of_range + assert(r.ec == std::errc::result_out_of_range); + } + else + { + // Otherwise, value is set to the parsed value, + assert(x == 1150); + // and the member ec is value-initialized. + assert(r.ec == std::errc{}); + } + assert(r.ptr == s + 5); + } + } +}; + +template +struct test_signed : roundtrip_test_base +{ + using roundtrip_test_base::test; + + void operator()() + { + test(-1); + test(-12); + test(-1, 10); + test(-12, 10); + test(-21734634, 10); + test(-2647, 2); + test(-0xcc1, 16); + + for (int b = 2; b < 37; ++b) + { + using xl = std::numeric_limits; + + test(0, b); + test(xl::lowest(), b); + test((xl::max)(), b); + } + + using std::from_chars; + std::from_chars_result r; + T x; + + { + // If the pattern allows for an optional sign, + // but the string has no digit characters following the sign, + char s[] = "- 9+12"; + r = from_chars(s, s + sizeof(s), x); + // no characters match the pattern. + assert(r.ptr == s); + assert(r.ec == std::errc::invalid_argument); + } + + { + char s[] = "9+12"; + r = from_chars(s, s + sizeof(s), x); + assert(r.ec == std::errc{}); + // The member ptr of the return value points to the first character + // not matching the pattern, + assert(r.ptr == s + 1); + assert(x == 9); + } + + { + char s[] = "12"; + r = from_chars(s, s + 2, x); + assert(r.ec == std::errc{}); + // or has the value last if all characters match. + assert(r.ptr == s + 2); + assert(x == 12); + } + + { + // '-' is the only sign that may appear + char s[] = "+30"; + // If no characters match the pattern, + r = from_chars(s, s + sizeof(s), x); + // value is unmodified, + assert(x == 12); + // the member ptr of the return value is first and + assert(r.ptr == s); + // the member ec is equal to errc::invalid_argument. + assert(r.ec == std::errc::invalid_argument); + } + } +}; + +int +main() +{ + run(integrals); + run(all_signed); +} diff --git a/test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp b/test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp new file mode 100644 index 000000000..e3d702a3a --- /dev/null +++ b/test/std/utilities/charconv/charconv.to.chars/integral.bool.fail.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// + +// In +// +// to_chars_result to_chars(char* first, char* last, Integral value, +// int base = 10) +// +// Integral cannot be bool. + +#include + +int main() +{ + using std::to_chars; + char buf[10]; + bool lv = true; + + to_chars(buf, buf + sizeof(buf), false); // expected-error {{call to deleted function}} + to_chars(buf, buf + sizeof(buf), lv, 16); // expected-error {{call to deleted function}} +} diff --git a/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp b/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp new file mode 100644 index 000000000..50ca5b190 --- /dev/null +++ b/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// + +// to_chars_result to_chars(char* first, char* last, Integral value, +// int base = 10) + +#include "charconv_test_helpers.h" + +template +struct test_basics : to_chars_test_base +{ + using to_chars_test_base::test; + using to_chars_test_base::test_value; + + void operator()() + { + test(0, "0"); + test(42, "42"); + test(32768, "32768"); + test(0, "0", 10); + test(42, "42", 10); + test(32768, "32768", 10); + test(0xf, "f", 16); + test(0xdeadbeaf, "deadbeaf", 16); + test(0755, "755", 8); + + for (int b = 2; b < 37; ++b) + { + using xl = std::numeric_limits; + + test_value(1, b); + test_value(xl::lowest(), b); + test_value((xl::max)(), b); + test_value((xl::max)() / 2, b); + } + } +}; + +template +struct test_signed : to_chars_test_base +{ + using to_chars_test_base::test; + using to_chars_test_base::test_value; + + void operator()() + { + test(-1, "-1"); + test(-12, "-12"); + test(-1, "-1", 10); + test(-12, "-12", 10); + test(-21734634, "-21734634", 10); + test(-2647, "-101001010111", 2); + test(-0xcc1, "-cc1", 16); + + for (int b = 2; b < 37; ++b) + { + using xl = std::numeric_limits; + + test_value(0, b); + test_value(xl::lowest(), b); + test_value((xl::max)(), b); + } + } +}; + +int +main() +{ + run(integrals); + run(all_signed); +} diff --git a/test/support/charconv_test_helpers.h b/test/support/charconv_test_helpers.h new file mode 100644 index 000000000..df1b00a67 --- /dev/null +++ b/test/support/charconv_test_helpers.h @@ -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. +// +//===----------------------------------------------------------------------===// + +#ifndef SUPPORT_CHARCONV_TEST_HELPERS_H +#define SUPPORT_CHARCONV_TEST_HELPERS_H + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +#if TEST_STD_VER <= 11 +#error This file requires C++14 +#endif + +using std::false_type; +using std::true_type; + +template +constexpr auto +is_non_narrowing(From a) -> decltype(To{a}, true_type()) +{ + return {}; +} + +template +constexpr auto +is_non_narrowing(...) -> false_type +{ + return {}; +} + +template +constexpr bool +_fits_in(T, true_type /* non-narrowing*/, ...) +{ + return true; +} + +template > +constexpr bool +_fits_in(T v, false_type, true_type /* T signed*/, true_type /* X signed */) +{ + return xl::lowest() <= v && v <= (xl::max)(); +} + +template > +constexpr bool +_fits_in(T v, false_type, true_type /* T signed */, false_type /* X unsigned*/) +{ + return 0 <= v && std::make_unsigned_t(v) <= (xl::max)(); +} + +template > +constexpr bool +_fits_in(T v, false_type, false_type /* T unsigned */, ...) +{ + return v <= std::make_unsigned_t((xl::max)()); +} + +template +constexpr bool +fits_in(T v) +{ + return _fits_in(v, is_non_narrowing(v), std::is_signed(), + std::is_signed()); +} + +template +struct to_chars_test_base +{ + template + void test(T v, char const (&expect)[N], Ts... args) + { + using std::to_chars; + std::to_chars_result r; + + constexpr size_t len = N - 1; + static_assert(len > 0, "expected output won't be empty"); + + if (!fits_in(v)) + return; + + r = to_chars(buf, buf + len - 1, X(v), args...); + assert(r.ptr == buf + len - 1); + assert(r.ec == std::errc::value_too_large); + + r = to_chars(buf, buf + sizeof(buf), X(v), args...); + assert(r.ptr == buf + len); + assert(r.ec == std::errc{}); + assert(memcmp(buf, expect, len) == 0); + } + + template + void test_value(X v, Ts... args) + { + using std::to_chars; + std::to_chars_result r; + + r = to_chars(buf, buf + sizeof(buf), v, args...); + assert(r.ec == std::errc{}); + *r.ptr = '\0'; + + auto a = fromchars(buf, r.ptr, args...); + assert(v == a); + + auto ep = r.ptr - 1; + r = to_chars(buf, ep, v, args...); + assert(r.ptr == ep); + assert(r.ec == std::errc::value_too_large); + } + +private: + static auto fromchars(char const* p, char const* ep, int base, true_type) + { + char* last; + auto r = strtoll(p, &last, base); + assert(last == ep); + + return r; + } + + static auto fromchars(char const* p, char const* ep, int base, false_type) + { + char* last; + auto r = strtoull(p, &last, base); + assert(last == ep); + + return r; + } + + static auto fromchars(char const* p, char const* ep, int base = 10) + { + return fromchars(p, ep, base, std::is_signed()); + } + + char buf[100]; +}; + +template +struct roundtrip_test_base +{ + template + void test(T v, Ts... args) + { + using std::from_chars; + using std::to_chars; + std::from_chars_result r2; + std::to_chars_result r; + X x = 0xc; + + if (fits_in(v)) + { + r = to_chars(buf, buf + sizeof(buf), v, args...); + assert(r.ec == std::errc{}); + + r2 = from_chars(buf, r.ptr, x, args...); + assert(r2.ptr == r.ptr); + assert(x == X(v)); + } + else + { + r = to_chars(buf, buf + sizeof(buf), v, args...); + assert(r.ec == std::errc{}); + + r2 = from_chars(buf, r.ptr, x, args...); + + if (std::is_signed::value && v < 0 && std::is_unsigned::value) + { + assert(x == 0xc); + assert(r2.ptr == buf); + assert(r.ec == std::errc::invalid_argument); + } + else + { + assert(x == 0xc); + assert(r2.ptr == r.ptr); + assert(r2.ec == std::errc::result_out_of_range); + } + } + } + +private: + char buf[100]; +}; + +template +struct type_list +{ +}; + +template +struct type_concat; + +template +struct type_concat, type_list> +{ + using type = type_list; +}; + +template +using concat_t = typename type_concat::type; + +template +constexpr auto concat(L1, L2) -> concat_t +{ + return {}; +} + +auto all_signed = type_list(); +auto all_unsigned = type_list(); +auto integrals = concat(all_signed, all_unsigned); + +template