Since I backported the Filesystem lib to the gcc-5-branch in mid-August there have been some bugfixes on trunk, and dual ABI support in libstdc++fs.a, so I'm backporting those changes to the branch too.
This also removes some empty TODO files I accidentally added on the branch, which were only meant to be in my local tree not checked in! Tested powerpc64le-linux, committed to gcc-5-branch.
commit aa25633dc15bdea41959ce3da3ba101fcb31bfbf Author: Jonathan Wakely <jwak...@redhat.com> Date: Fri Oct 2 22:06:38 2015 +0100 Backport Filesystem TS fixes from mainline. PR libstdc++/67173 PR libstdc++/67747 * acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check _XOPEN_VERSION and PATH_MAX for _GLIBCXX_USE_REALPATH. Remove _GLIBCXX_ prefix from HAVE_STRUCT_DIRENT_D_TYPE. * config.h.in: Regenerate. * configure: Regenerate. * include/bits/locale_conv.h [!_GLIBCXX_USE_WCHAR_T] (__do_str_codecvt, __str_codecvt_in, __str_codecvt_out): Enable. * include/experimental/fs_dir.h (operator==, operator==): Use owner_before instead of pointer equality. (directory_iterator(std::shared_ptr<_Dir>, error_code*)): Remove. * include/experimental/fs_path.h (operator==, operator==): * include/experimental/fs_path.h [!_GLIBCXX_USE_WCHAR_T] (path::wstring, path::generic_wstring): Disable. * src/filesystem/path.cc (path::_S_convert_loc) [!_GLIBCXX_USE_WCHAR_T]: Skip conversion. * src/filesystem/Makefile.am: Add cxx11_abi_sources. * src/filesystem/Makefile.in: Regenerate. * src/filesystem/cow-dir.cc: New. * src/filesystem/cow-ops.cc: New. * src/filesystem/cow-path.cc: New. * src/filesystem/dir.cc: Define macro for new ABI. (native_readdir): Remove. (_Dir::advance): Use readdir instead of native_readdir. (recursive_directory_iterator(const path&, directory_options, error_code*)): Use swap instead of reset. (ErrorCode): Remove. (_Dir::advance): Change ErrorCode parameter to error_code*, add directory_options parameter and check it on error. (opendir): Rename to open_dir to avoid clashing with macro. Change ErrorCode parameter to error_code*. (make_shared_dir): Remove. (native_readdir) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Don't set errno. (directory_iterator(std::shared_ptr<_Dir>, error_code*)): Remove. (directory_iterator(const path&, directory_options, error_code*)): Pass options to _Dir::advance and create non-end iterator on error. (recursive_directory_iterator(const path&, directory_options, error_code*)): Clear error_code on ignored error, create non-end iterator otherwise. (recursive_directory_iterator::increment): Pass _M_options to _Dir::advance. (recursive_directory_iterator::pop): Likewise. * src/filesystem/ops.cc: Define macro for new ABI. (canonical) [!_GLIBCXX_USE_REALPATH]: Add alternative implementation. (is_dot, is_dotdot): Define new helpers. (create_directories): Fix error handling. * src/filesystem/path.cc: Define macro for new ABI. (path::_S_convert_loc) [!_GLIBCXX_USE_WCHAR_T]: Skip conversion. * testsuite/experimental/filesystem/iterators/directory_iterator.cc: New. * testsuite/experimental/filesystem/iterators/ recursive_directory_iterator.cc: New. * testsuite/experimental/filesystem/operations/canonical.cc: New. * testsuite/experimental/filesystem/operations/create_directories.cc: New. * testsuite/experimental/filesystem/operations/exists.cc: Add more tests. * testsuite/experimental/filesystem/operations/absolute.cc: Add test variables. * testsuite/experimental/filesystem/operations/copy.cc: Likewise. * testsuite/experimental/filesystem/operations/current_path.cc: Likewise. * testsuite/experimental/filesystem/operations/file_size.cc: Likewise. * testsuite/experimental/filesystem/operations/status.cc: Likewise. * testsuite/experimental/filesystem/operations/temp_directory_path.cc: Likewise. * testsuite/experimental/filesystem/path/assign/assign.cc: Check for wchar_t support. * testsuite/experimental/filesystem/path/concat/strings.cc: Likewise. * testsuite/experimental/filesystem/path/construct/range.cc: Likewise. diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index c6e1e35..d4bf81b 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -3962,20 +3962,31 @@ dnl [glibcxx_cv_dirent_d_type=no]) ]) if test $glibcxx_cv_dirent_d_type = yes; then - AC_DEFINE(_GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE, 1, [Define to 1 if `d_type' is a member of `struct dirent'.]) + AC_DEFINE(HAVE_STRUCT_DIRENT_D_TYPE, 1, [Define to 1 if `d_type' is a member of `struct dirent'.]) fi AC_MSG_RESULT($glibcxx_cv_dirent_d_type) dnl AC_MSG_CHECKING([for realpath]) AC_CACHE_VAL(glibcxx_cv_realpath, [dnl GCC_TRY_COMPILE_OR_LINK( - [#include <stdlib.h>], - [char *tmp = realpath((const char*)NULL, (char*)NULL);], + [ + #include <stdlib.h> + #include <unistd.h> + ], + [ + #if _XOPEN_VERSION < 500 + #error + #elif _XOPEN_VERSION >= 700 || defined(PATH_MAX) + char *tmp = realpath((const char*)NULL, (char*)NULL); + #else + #error + #endif + ], [glibcxx_cv_realpath=yes], [glibcxx_cv_realpath=no]) ]) if test $glibcxx_cv_realpath = yes; then - AC_DEFINE(_GLIBCXX_USE_REALPATH, 1, [Define if realpath is available in <stdlib.h>.]) + AC_DEFINE(_GLIBCXX_USE_REALPATH, 1, [Define if usable realpath is available in <stdlib.h>.]) fi AC_MSG_RESULT($glibcxx_cv_realpath) dnl diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 1d1a7db..d4e28bc 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -378,6 +378,9 @@ /* Define to 1 if you have the `strtold' function. */ #undef HAVE_STRTOLD +/* Define to 1 if `d_type' is a member of `struct dirent'. */ +#undef HAVE_STRUCT_DIRENT_D_TYPE + /* Define if strxfrm_l is available in <string.h>. */ #undef HAVE_STRXFRM_L @@ -738,9 +741,6 @@ /* Define if gthreads library is available. */ #undef _GLIBCXX_HAS_GTHREADS -/* Define to 1 if `d_type' is a member of `struct dirent'. */ -#undef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE - /* Define to 1 if a full hosted library is built, or 0 if freestanding. */ #undef _GLIBCXX_HOSTED @@ -879,7 +879,7 @@ of TR1 (Chapter 5.1). */ #undef _GLIBCXX_USE_RANDOM_TR1 -/* Define if realpath is available in <stdlib.h>. */ +/* Define if usable realpath is available in <stdlib.h>. */ #undef _GLIBCXX_USE_REALPATH /* Defined if sched_yield is available. */ diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index ccdbaa4..ba59fba 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -78993,7 +78993,7 @@ fi if test $glibcxx_cv_dirent_d_type = yes; then -$as_echo "#define _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE 1" >>confdefs.h +$as_echo "#define HAVE_STRUCT_DIRENT_D_TYPE 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_dirent_d_type" >&5 @@ -79006,11 +79006,22 @@ else if test x$gcc_no_link = xyes; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include <stdlib.h> + + #include <stdlib.h> + #include <unistd.h> + int main () { -char *tmp = realpath((const char*)NULL, (char*)NULL); + + #if _XOPEN_VERSION < 500 + #error + #elif _XOPEN_VERSION >= 700 || defined(PATH_MAX) + char *tmp = realpath((const char*)NULL, (char*)NULL); + #else + #error + #endif + ; return 0; } @@ -79027,11 +79038,22 @@ else fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include <stdlib.h> + + #include <stdlib.h> + #include <unistd.h> + int main () { -char *tmp = realpath((const char*)NULL, (char*)NULL); + + #if _XOPEN_VERSION < 500 + #error + #elif _XOPEN_VERSION >= 700 || defined(PATH_MAX) + char *tmp = realpath((const char*)NULL, (char*)NULL); + #else + #error + #endif + ; return 0; } diff --git a/libstdc++-v3/include/bits/locale_conv.h b/libstdc++-v3/include/bits/locale_conv.h index 146f78b..16b4875 100644 --- a/libstdc++-v3/include/bits/locale_conv.h +++ b/libstdc++-v3/include/bits/locale_conv.h @@ -44,8 +44,6 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION -#ifdef _GLIBCXX_USE_WCHAR_T - /** * @addtogroup locales * @{ @@ -157,6 +155,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __str_codecvt_out(__first, __last, __outstr, __cvt, __state, __n); } +#ifdef _GLIBCXX_USE_WCHAR_T + _GLIBCXX_BEGIN_NAMESPACE_CXX11 /// String conversions @@ -533,10 +533,10 @@ _GLIBCXX_END_NAMESPACE_CXX11 bool _M_always_noconv; }; - /// @} group locales - #endif // _GLIBCXX_USE_WCHAR_T + /// @} group locales + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/experimental/fs_dir.h b/libstdc++-v3/include/experimental/fs_dir.h index d46d41b..0c5253f 100644 --- a/libstdc++-v3/include/experimental/fs_dir.h +++ b/libstdc++-v3/include/experimental/fs_dir.h @@ -201,14 +201,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __tmp; } - friend bool - operator==(const directory_iterator& __lhs, - const directory_iterator& __rhs) - { return __lhs._M_dir == __rhs._M_dir; } - private: directory_iterator(const path&, directory_options, error_code*); - directory_iterator(std::shared_ptr<_Dir>, error_code*); + + friend bool + operator==(const directory_iterator& __lhs, + const directory_iterator& __rhs); friend class recursive_directory_iterator; @@ -222,6 +220,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 end(directory_iterator) { return directory_iterator(); } inline bool + operator==(const directory_iterator& __lhs, const directory_iterator& __rhs) + { + return !__rhs._M_dir.owner_before(__lhs._M_dir) + && !__lhs._M_dir.owner_before(__rhs._M_dir); + } + + inline bool operator!=(const directory_iterator& __lhs, const directory_iterator& __rhs) { return !(__lhs == __rhs); } @@ -287,14 +292,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 void disable_recursion_pending() { _M_pending = false; } - friend bool - operator==(const recursive_directory_iterator& __lhs, - const recursive_directory_iterator& __rhs) - { return __lhs._M_dirs == __rhs._M_dirs; } - private: recursive_directory_iterator(const path&, directory_options, error_code*); + friend bool + operator==(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs); + struct _Dir_stack; std::shared_ptr<_Dir_stack> _M_dirs; directory_options _M_options; @@ -308,6 +312,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 end(recursive_directory_iterator) { return recursive_directory_iterator(); } inline bool + operator==(const recursive_directory_iterator& __lhs, + const recursive_directory_iterator& __rhs) + { + return !__rhs._M_dirs.owner_before(__lhs._M_dirs) + && !__lhs._M_dirs.owner_before(__rhs._M_dirs); + } + + inline bool operator!=(const recursive_directory_iterator& __lhs, const recursive_directory_iterator& __rhs) { return !(__lhs == __rhs); } diff --git a/libstdc++-v3/include/experimental/fs_path.h b/libstdc++-v3/include/experimental/fs_path.h index d103312..1632a7e 100644 --- a/libstdc++-v3/include/experimental/fs_path.h +++ b/libstdc++-v3/include/experimental/fs_path.h @@ -279,7 +279,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 string(const _Allocator& __a = _Allocator()) const; std::string string() const; +#if _GLIBCXX_USE_WCHAR_T std::wstring wstring() const; +#endif std::string u8string() const; std::u16string u16string() const; std::u32string u32string() const; @@ -291,7 +293,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 generic_string(const _Allocator& __a = _Allocator()) const; std::string generic_string() const; +#if _GLIBCXX_USE_WCHAR_T std::wstring generic_wstring() const; +#endif std::string generic_u8string() const; std::u16string generic_u16string() const; std::u32string generic_u32string() const; @@ -828,8 +832,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 inline std::string path::string() const { return string<char>(); } +#if _GLIBCXX_USE_WCHAR_T inline std::wstring path::wstring() const { return string<wchar_t>(); } +#endif inline std::string path::u8string() const @@ -865,8 +871,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 inline std::string path::generic_string() const { return string(); } +#if _GLIBCXX_USE_WCHAR_T inline std::wstring path::generic_wstring() const { return wstring(); } +#endif inline std::string path::generic_u8string() const { return u8string(); } diff --git a/libstdc++-v3/src/filesystem/Makefile.am b/libstdc++-v3/src/filesystem/Makefile.am index 128cba9..8e332ec4 100644 --- a/libstdc++-v3/src/filesystem/Makefile.am +++ b/libstdc++-v3/src/filesystem/Makefile.am @@ -26,10 +26,20 @@ toolexeclib_LTLIBRARIES = libstdc++fs.la headers = +if ENABLE_DUAL_ABI +cxx11_abi_sources = \ + cow-dir.cc \ + cow-ops.cc \ + cow-path.cc +else +cxx11_abi_sources = +endif + sources = \ dir.cc \ ops.cc \ - path.cc + path.cc \ + ${cxx11_abi_sources} # vpath % $(top_srcdir)/src/filesystem diff --git a/libstdc++-v3/src/filesystem/Makefile.in b/libstdc++-v3/src/filesystem/Makefile.in index 97c0832..bbc45a8 100644 --- a/libstdc++-v3/src/filesystem/Makefile.in +++ b/libstdc++-v3/src/filesystem/Makefile.in @@ -112,8 +112,10 @@ am__uninstall_files_from_dir = { \ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" LTLIBRARIES = $(toolexeclib_LTLIBRARIES) libstdc__fs_la_LIBADD = -am__objects_1 = dir.lo ops.lo path.lo -am_libstdc__fs_la_OBJECTS = $(am__objects_1) +@ENABLE_DUAL_ABI_TRUE@am__objects_1 = cow-dir.lo cow-ops.lo \ +@ENABLE_DUAL_ABI_TRUE@ cow-path.lo +am__objects_2 = dir.lo ops.lo path.lo $(am__objects_1) +am_libstdc__fs_la_OBJECTS = $(am__objects_2) libstdc__fs_la_OBJECTS = $(am_libstdc__fs_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = @@ -350,13 +352,20 @@ WARN_CXXFLAGS = \ # -I/-D flags to pass when compiling. -AM_CPPFLAGS = $(GLIBCXX_INCLUDES) +AM_CPPFLAGS = $(GLIBCXX_INCLUDES) $(CPPFLAGS) toolexeclib_LTLIBRARIES = libstdc++fs.la headers = +@ENABLE_DUAL_ABI_FALSE@cxx11_abi_sources = +@ENABLE_DUAL_ABI_TRUE@cxx11_abi_sources = \ +@ENABLE_DUAL_ABI_TRUE@ cow-dir.cc \ +@ENABLE_DUAL_ABI_TRUE@ cow-ops.cc \ +@ENABLE_DUAL_ABI_TRUE@ cow-path.cc + sources = \ dir.cc \ ops.cc \ - path.cc + path.cc \ + ${cxx11_abi_sources} # vpath % $(top_srcdir)/src/filesystem diff --git a/libstdc++-v3/src/filesystem/cow-dir.cc b/libstdc++-v3/src/filesystem/cow-dir.cc new file mode 100644 index 0000000..b4175ef --- /dev/null +++ b/libstdc++-v3/src/filesystem/cow-dir.cc @@ -0,0 +1,26 @@ +// Class filesystem::directory_entry etc. -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#define _GLIBCXX_USE_CXX11_ABI 0 +#include "dir.cc" diff --git a/libstdc++-v3/src/filesystem/cow-ops.cc b/libstdc++-v3/src/filesystem/cow-ops.cc new file mode 100644 index 0000000..6096dec --- /dev/null +++ b/libstdc++-v3/src/filesystem/cow-ops.cc @@ -0,0 +1,26 @@ +// Filesystem operations -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#define _GLIBCXX_USE_CXX11_ABI 0 +#include "ops.cc" diff --git a/libstdc++-v3/src/filesystem/cow-path.cc b/libstdc++-v3/src/filesystem/cow-path.cc new file mode 100644 index 0000000..386df59 --- /dev/null +++ b/libstdc++-v3/src/filesystem/cow-path.cc @@ -0,0 +1,26 @@ +// Class filesystem::path -*- C++ -*- + +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#define _GLIBCXX_USE_CXX11_ABI 0 +#include "path.cc" diff --git a/libstdc++-v3/src/filesystem/dir.cc b/libstdc++-v3/src/filesystem/dir.cc index 016a78d..63c10e7 100644 --- a/libstdc++-v3/src/filesystem/dir.cc +++ b/libstdc++-v3/src/filesystem/dir.cc @@ -22,6 +22,10 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // <http://www.gnu.org/licenses/>. +#ifndef _GLIBCXX_USE_CXX11_ABI +# define _GLIBCXX_USE_CXX11_ABI 1 +#endif + #include <experimental/filesystem> #include <utility> #include <stack> @@ -43,28 +47,6 @@ namespace fs = std::experimental::filesystem; -namespace -{ - struct ErrorCode - { - ErrorCode(std::error_code* p) : ec(p) { } - - ErrorCode(ErrorCode&& e) : ec(std::exchange(e.ec, nullptr)) { } - - ~ErrorCode() { if (ec) ec->clear(); } - - void assign(int err) - { - ec->assign(err, std::generic_category()); - ec = nullptr; - } - - explicit operator bool() { return ec != nullptr; } - - std::error_code* ec; - }; -} - struct fs::_Dir { _Dir() : dirp(nullptr) { } @@ -80,7 +62,7 @@ struct fs::_Dir ~_Dir() { if (dirp) ::closedir(dirp); } - bool advance(ErrorCode); + bool advance(std::error_code*, directory_options = directory_options::none); DIR* dirp; fs::path path; @@ -91,14 +73,21 @@ struct fs::_Dir namespace { template<typename Bitmask> - inline bool is_set(Bitmask obj, Bitmask bits) + inline bool + is_set(Bitmask obj, Bitmask bits) { return (obj & bits) != Bitmask::none; } - fs::_Dir - opendir(const fs::path& p, fs::directory_options options, ErrorCode ec) + // Returns {dirp, p} on success, {nullptr, p} on error. + // If an ignored EACCES error occurs returns {}. + inline fs::_Dir + open_dir(const fs::path& p, fs::directory_options options, + std::error_code* ec) { + if (ec) + ec->clear(); + if (DIR* dirp = ::opendir(p.c_str())) return {dirp, p}; @@ -112,20 +101,12 @@ namespace "directory iterator cannot open directory", p, std::error_code(err, std::generic_category()))); - ec.assign(err); - return {}; - } - - inline std::shared_ptr<fs::_Dir> - make_shared_dir(fs::_Dir&& dir) - { - if (dir.dirp) - return std::make_shared<fs::_Dir>(std::move(dir)); - return {}; + ec->assign(err, std::generic_category()); + return {nullptr, p}; } inline fs::file_type - get_file_type(const dirent& d __attribute__((__unused__))) + get_file_type(const ::dirent& d __attribute__((__unused__))) { #ifdef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE switch (d.d_type) @@ -153,42 +134,41 @@ namespace return fs::file_type::none; #endif } - - int - native_readdir(DIR* dirp, ::dirent*& entryp) - { -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - errno = 0; - if ((entryp = ::readdir(dirp))) - return 0; - return errno; -#else - return ::readdir_r(dirp, entryp, &entryp); -#endif - } } + +// Returns false when the end of the directory entries is reached. +// Reports errors by setting ec or throwing. bool -fs::_Dir::advance(ErrorCode ec) +fs::_Dir::advance(error_code* ec, directory_options options) { - ::dirent ent; - ::dirent* result = &ent; - if (int err = native_readdir(dirp, result)) + if (ec) + ec->clear(); + + int err = std::exchange(errno, 0); + const auto entp = readdir(dirp); + std::swap(errno, err); + + if (entp) { + // skip past dot and dot-dot + if (!strcmp(entp->d_name, ".") || !strcmp(entp->d_name, "..")) + return advance(ec, options); + entry = fs::directory_entry{path / entp->d_name}; + type = get_file_type(*entp); + return true; + } + else if (err) + { + if (err == EACCES + && is_set(options, directory_options::skip_permission_denied)) + return false; + if (!ec) _GLIBCXX_THROW_OR_ABORT(filesystem_error( "directory iterator cannot advance", std::error_code(err, std::generic_category()))); - ec.assign(err); - return true; - } - else if (result != nullptr) - { - // skip past dot and dot-dot - if (!strcmp(ent.d_name, ".") || !strcmp(ent.d_name, "..")) - return advance(std::move(ec)); - entry = fs::directory_entry{path / ent.d_name}; - type = get_file_type(ent); + ec->assign(err, std::generic_category()); return true; } else @@ -202,15 +182,21 @@ fs::_Dir::advance(ErrorCode ec) fs::directory_iterator:: directory_iterator(const path& p, directory_options options, error_code* ec) -: directory_iterator(make_shared_dir(opendir(p, options, ec)), ec) -{ } - -fs::directory_iterator:: -directory_iterator(std::shared_ptr<_Dir> dir, error_code* ec) -: _M_dir(std::move(dir)) { - if (_M_dir && !_M_dir->advance(ec)) - _M_dir.reset(); + _Dir dir = open_dir(p, options, ec); + + if (dir.dirp) + { + auto sp = std::make_shared<fs::_Dir>(std::move(dir)); + if (sp->advance(ec, options)) + _M_dir.swap(sp); + } + else if (!dir.path.empty()) + { + // An error occurred, we need a non-empty shared_ptr so that *this will + // not compare equal to the end iterator. + _M_dir.reset(static_cast<fs::_Dir*>(nullptr)); + } } const fs::directory_entry& @@ -257,22 +243,26 @@ struct fs::recursive_directory_iterator::_Dir_stack : std::stack<_Dir> fs::recursive_directory_iterator:: recursive_directory_iterator(const path& p, directory_options options, - error_code* ec) + error_code* ec) : _M_options(options), _M_pending(true) { if (DIR* dirp = ::opendir(p.c_str())) { - _M_dirs = std::make_shared<_Dir_stack>(); - _M_dirs->push(_Dir{ dirp, p }); - if (!_M_dirs->top().advance(ec)) - _M_dirs.reset(); + auto sp = std::make_shared<_Dir_stack>(); + sp->push(_Dir{ dirp, p }); + if (sp->top().advance(ec)) + _M_dirs.swap(sp); } else { const int err = errno; if (err == EACCES && is_set(options, fs::directory_options::skip_permission_denied)) - return; + { + if (ec) + ec->clear(); + return; + } if (!ec) _GLIBCXX_THROW_OR_ABORT(filesystem_error( @@ -280,6 +270,10 @@ recursive_directory_iterator(const path& p, directory_options options, std::error_code(err, std::generic_category()))); ec->assign(err, std::generic_category()); + + // An error occurred, we need a non-empty shared_ptr so that *this will + // not compare equal to the end iterator. + _M_dirs.reset(static_cast<_Dir_stack*>(nullptr)); } } @@ -358,21 +352,14 @@ fs::recursive_directory_iterator::increment(error_code& ec) noexcept if (std::exchange(_M_pending, true) && recurse(top, _M_options, ec)) { - _Dir dir = opendir(top.entry.path(), _M_options, &ec); - if (ec.value()) + _Dir dir = open_dir(top.entry.path(), _M_options, &ec); + if (ec) return *this; if (dir.dirp) - { _M_dirs->push(std::move(dir)); - if (!_M_dirs->top().advance(&ec)) // dir is empty - pop(); - return *this; - } - // else skip permission denied and continue in parent dir } - ec.clear(); - while (!_M_dirs->top().advance(&ec) && !ec.value()) + while (!_M_dirs->top().advance(&ec, _M_options) && !ec) { _M_dirs->pop(); if (_M_dirs->empty()) @@ -399,5 +386,5 @@ fs::recursive_directory_iterator::pop() _M_dirs.reset(); return; } - } while (!_M_dirs->top().advance(nullptr)); + } while (!_M_dirs->top().advance(nullptr, _M_options)); } diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc index 661685a..8152560 100644 --- a/libstdc++-v3/src/filesystem/ops.cc +++ b/libstdc++-v3/src/filesystem/ops.cc @@ -22,12 +22,17 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // <http://www.gnu.org/licenses/>. +#ifndef _GLIBCXX_USE_CXX11_ABI +# define _GLIBCXX_USE_CXX11_ABI 1 +#endif + #include <experimental/filesystem> #include <functional> #include <stack> #include <stdlib.h> #include <stdio.h> #include <errno.h> +#include <limits.h> // PATH_MAX #ifdef _GLIBCXX_HAVE_UNISTD_H # include <unistd.h> # if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H) @@ -84,6 +89,24 @@ fs::absolute(const path& p, const path& base) namespace { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + inline bool is_dot(wchar_t c) { return c == L'.'; } +#else + inline bool is_dot(char c) { return c == '.'; } +#endif + + inline bool is_dot(const fs::path& path) + { + const auto& filename = path.native(); + return filename.size() == 1 && is_dot(filename[0]); + } + + inline bool is_dotdot(const fs::path& path) + { + const auto& filename = path.native(); + return filename.size() == 2 && is_dot(filename[0]) && is_dot(filename[1]); + } + struct free_as_in_malloc { void operator()(void* p) const { ::free(p); } @@ -95,19 +118,92 @@ namespace fs::path fs::canonical(const path& p, const path& base, error_code& ec) { - path can; + const path pa = absolute(p, base); + path result; + #ifdef _GLIBCXX_USE_REALPATH - if (char_ptr rp = char_ptr{::realpath(absolute(p, base).c_str(), nullptr)}) + char_ptr buf{ nullptr }; +# if _XOPEN_VERSION < 700 + // Not safe to call realpath(path, NULL) + buf.reset( (char*)::malloc(PATH_MAX) ); +# endif + if (char* rp = ::realpath(pa.c_str(), buf.get())) { - can.assign(rp.get()); + if (buf == nullptr) + buf.reset(rp); + result.assign(rp); ec.clear(); + return result; + } + if (errno != ENAMETOOLONG) + { + ec.assign(errno, std::generic_category()); + return result; } - else - ec.assign(errno, std::generic_category()); -#else - ec = std::make_error_code(std::errc::not_supported); #endif - return can; + + if (!exists(pa, ec)) + return result; + // else: we know there are (currently) no unresolvable symlink loops + + result = pa.root_path(); + + deque<path> cmpts; + for (auto& f : pa.relative_path()) + cmpts.push_back(f); + + int max_allowed_symlinks = 40; + + while (!cmpts.empty() && !ec) + { + path f = std::move(cmpts.front()); + cmpts.pop_front(); + + if (is_dot(f)) + { + if (!is_directory(result, ec) && !ec) + ec.assign(ENOTDIR, std::generic_category()); + } + else if (is_dotdot(f)) + { + auto parent = result.parent_path(); + if (parent.empty()) + result = pa.root_path(); + else + result.swap(parent); + } + else + { + result /= f; + + if (is_symlink(result, ec)) + { + path link = read_symlink(result, ec); + if (!ec) + { + if (--max_allowed_symlinks == 0) + ec.assign(ELOOP, std::generic_category()); + else + { + if (link.is_absolute()) + { + result = link.root_path(); + link = link.relative_path(); + } + else + result.remove_filename(); + + cmpts.insert(cmpts.begin(), link.begin(), link.end()); + } + } + } + } + } + + if (ec || !exists(result, ec)) + result.clear(); + + return result; } fs::path @@ -496,19 +592,36 @@ fs::create_directories(const path& p) bool fs::create_directories(const path& p, error_code& ec) noexcept { + if (p.empty()) + { + ec = std::make_error_code(errc::invalid_argument); + return false; + } std::stack<path> missing; path pp = p; - ec.clear(); - while (!p.empty() && !exists(pp, ec) && !ec.value()) + + while (!pp.empty() && status(pp, ec).type() == file_type::not_found) { - missing.push(pp); - pp = pp.parent_path(); + ec.clear(); + const auto& filename = pp.filename(); + if (!is_dot(filename) && !is_dotdot(filename)) + missing.push(pp); + pp.remove_filename(); } - while (!missing.empty() && !ec.value()) + + if (ec || missing.empty()) + return false; + + do { - create_directory(missing.top(), ec); + const path& top = missing.top(); + create_directory(top, ec); + if (ec && is_directory(top)) + ec.clear(); missing.pop(); } + while (!missing.empty() && !ec); + return missing.empty(); } diff --git a/libstdc++-v3/src/filesystem/path.cc b/libstdc++-v3/src/filesystem/path.cc index a5441b9..e9fe465 100644 --- a/libstdc++-v3/src/filesystem/path.cc +++ b/libstdc++-v3/src/filesystem/path.cc @@ -22,6 +22,10 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // <http://www.gnu.org/licenses/>. +#ifndef _GLIBCXX_USE_CXX11_ABI +# define _GLIBCXX_USE_CXX11_ABI 1 +#endif + #include <experimental/filesystem> using std::experimental::filesystem::path; @@ -437,8 +441,9 @@ path::_M_trim() path::string_type path::_S_convert_loc(const char* __first, const char* __last, - const std::locale& __loc) + const std::locale& __loc) { +#if _GLIBCXX_USE_WCHAR_T auto& __cvt = std::use_facet<codecvt<wchar_t, char, mbstate_t>>(__loc); basic_string<wchar_t> __ws; if (!__str_codecvt_in(__first, __last, __ws, __cvt)) @@ -450,6 +455,9 @@ path::_S_convert_loc(const char* __first, const char* __last, #else return _Cvt<wchar_t>::_S_convert(__ws.data(), __ws.data() + __ws.size()); #endif +#else + return {__first, __last}; +#endif } std::size_t diff --git a/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc b/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc new file mode 100644 index 0000000..56b808d --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/iterators/directory_iterator.cc @@ -0,0 +1,77 @@ +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +#include <experimental/filesystem> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +namespace fs = std::experimental::filesystem; + +void +test01() +{ + bool test __attribute__((unused)) = false; + std::error_code ec; + + // Test non-existent path. + const auto p = __gnu_test::nonexistent_path(); + fs::directory_iterator iter(p, ec); + VERIFY( ec ); + VERIFY( iter != fs::directory_iterator() ); + + // Test empty directory. + create_directory(p, fs::current_path(), ec); + VERIFY( !ec ); + iter = fs::directory_iterator(p, ec); + VERIFY( !ec ); + VERIFY( iter == fs::directory_iterator() ); + + // Test non-empty directory. + create_directory_symlink(p, p / "l", ec); + VERIFY( !ec ); + iter = fs::directory_iterator(p, ec); + VERIFY( !ec ); + VERIFY( iter != fs::directory_iterator() ); + VERIFY( iter->path() == p/"l" ); + ++iter; + VERIFY( iter == fs::directory_iterator() ); + + // Test inaccessible directory. + permissions(p, fs::perms::none, ec); + VERIFY( !ec ); + iter = fs::directory_iterator(p, ec); + VERIFY( ec ); + VERIFY( iter != fs::directory_iterator() ); + + // Test inaccessible directory, skipping permission denied. + const auto opts = fs::directory_options::skip_permission_denied; + iter = fs::directory_iterator(p, opts, ec); + VERIFY( !ec ); + VERIFY( iter == fs::directory_iterator() ); + + permissions(p, fs::perms::owner_all, ec); + remove_all(p, ec); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc b/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc new file mode 100644 index 0000000..9424c80 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/iterators/recursive_directory_iterator.cc @@ -0,0 +1,104 @@ +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +#include <experimental/filesystem> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +namespace fs = std::experimental::filesystem; + +void +test01() +{ + bool test __attribute__((unused)) = false; + std::error_code ec; + + // Test non-existent path. + const auto p = __gnu_test::nonexistent_path(); + fs::recursive_directory_iterator iter(p, ec); + VERIFY( ec ); + VERIFY( iter != fs::recursive_directory_iterator() ); + + // Test empty directory. + create_directory(p, fs::current_path(), ec); + VERIFY( !ec ); + iter = fs::recursive_directory_iterator(p, ec); + VERIFY( !ec ); + VERIFY( iter == fs::recursive_directory_iterator() ); + + // Test non-empty directory. + create_directories(p / "d1/d2"); + VERIFY( !ec ); + iter = fs::recursive_directory_iterator(p, ec); + VERIFY( !ec ); + VERIFY( iter != fs::recursive_directory_iterator() ); + VERIFY( iter->path() == p/"d1" ); + ++iter; + VERIFY( iter->path() == p/"d1/d2" ); + ++iter; + VERIFY( iter == fs::recursive_directory_iterator() ); + + // Test inaccessible directory. + permissions(p, fs::perms::none, ec); + VERIFY( !ec ); + iter = fs::recursive_directory_iterator(p, ec); + VERIFY( ec ); + VERIFY( iter != fs::recursive_directory_iterator() ); + + // Test inaccessible directory, skipping permission denied. + const auto opts = fs::directory_options::skip_permission_denied; + iter = fs::recursive_directory_iterator(p, opts, ec); + VERIFY( !ec ); + VERIFY( iter == fs::recursive_directory_iterator() ); + + // Test inaccessible sub-directory. + permissions(p, fs::perms::owner_all, ec); + VERIFY( !ec ); + permissions(p/"d1/d2", fs::perms::none, ec); + VERIFY( !ec ); + iter = fs::recursive_directory_iterator(p, ec); + VERIFY( !ec ); + VERIFY( iter != fs::recursive_directory_iterator() ); + VERIFY( iter->path() == p/"d1" ); + ++iter; // should recurse into d1 + VERIFY( iter->path() == p/"d1/d2" ); + iter.increment(ec); // should fail to recurse into p/d1/d2 + VERIFY( ec ); + + // Test inaccessible sub-directory, skipping permission denied. + iter = fs::recursive_directory_iterator(p, opts, ec); + VERIFY( !ec ); + VERIFY( iter != fs::recursive_directory_iterator() ); + VERIFY( iter->path() == p/"d1" ); + ++iter; // should recurse into d1 + VERIFY( iter->path() == p/"d1/d2" ); + iter.increment(ec); // should fail to recurse into p/d1/d2, so skip it + VERIFY( !ec ); + VERIFY( iter == fs::recursive_directory_iterator() ); + + permissions(p/"d1/d2", fs::perms::owner_all, ec); + remove_all(p, ec); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc index 14625b5..f7507f5 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc @@ -29,6 +29,8 @@ using std::experimental::filesystem::path; void test01() { + bool test __attribute__((unused)) = false; + for (const path& p : __gnu_test::test_paths) VERIFY( absolute(p).is_absolute() ); } @@ -36,6 +38,8 @@ test01() void test02() { + bool test __attribute__((unused)) = false; + path p1("/"); VERIFY( absolute(p1) == p1 ); VERIFY( absolute(p1, "/bar") == p1 ); diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/canonical.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/canonical.cc new file mode 100644 index 0000000..5091a70 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/canonical.cc @@ -0,0 +1,66 @@ +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +#include <experimental/filesystem> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +namespace fs = std::experimental::filesystem; + +void +test01() +{ + bool test __attribute__((unused)) = false; + + std::error_code ec; + auto p = __gnu_test::nonexistent_path(); + canonical( p, ec ); + VERIFY( ec ); + + p = fs::current_path(); + canonical( p, ec ); + VERIFY( !ec ); + + p = "/"; + p = canonical( p, ec ); + VERIFY( p == "/" ); + VERIFY( !ec ); + + p = "/."; + p = canonical( p, ec ); + VERIFY( p == "/" ); + VERIFY( !ec ); + + p = "/.."; + p = canonical( p, ec ); + VERIFY( p == "/" ); + VERIFY( !ec ); + + p = "/../.././."; + p = canonical( p, ec ); + VERIFY( p == "/" ); + VERIFY( !ec ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc index 2410c80..35d49f0 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc @@ -29,6 +29,8 @@ using std::experimental::filesystem::path; void test01() { + bool test __attribute__((unused)) = false; + for (const path& p : __gnu_test::test_paths) VERIFY( absolute(p).is_absolute() ); } @@ -36,6 +38,8 @@ test01() void test02() { + bool test __attribute__((unused)) = false; + path p1("/"); VERIFY( absolute(p1) == p1 ); VERIFY( absolute(p1, "/bar") == p1 ); diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directories.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directories.cc new file mode 100644 index 0000000..b84d966 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directories.cc @@ -0,0 +1,75 @@ +// Copyright (C) 2015 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++11 -lstdc++fs" } +// { dg-require-filesystem-ts "" } + +#include <experimental/filesystem> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +namespace fs = std::experimental::filesystem; + +void +test01() +{ + bool test __attribute__((unused)) = false; + std::error_code ec; + + // Test empty path. + bool b = fs::create_directories( "", ec ); + VERIFY( ec ); + VERIFY( !b ); + + // Test existing path. + b = fs::create_directories( fs::current_path(), ec ); + VERIFY( !ec ); + VERIFY( !b ); + + // Test non-existent path. + const auto p = __gnu_test::nonexistent_path(); + b = fs::create_directories( p, ec ); + VERIFY( !ec ); + VERIFY( b ); + VERIFY( is_directory(p) ); + + b = fs::create_directories( p/".", ec ); + VERIFY( !ec ); + VERIFY( !b ); + + b = fs::create_directories( p/"..", ec ); + VERIFY( !ec ); + VERIFY( !b ); + + b = fs::create_directories( p/"d1/d2/d3", ec ); + VERIFY( !ec ); + VERIFY( b ); + VERIFY( is_directory(p/"d1/d2/d3") ); + + b = fs::create_directories( p/"./d4/../d5", ec ); + VERIFY( !ec ); + VERIFY( b ); + VERIFY( is_directory(p/"./d4/../d5") ); + + remove_all(p, ec); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc index c242ac0..81ade73 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc @@ -29,6 +29,8 @@ namespace fs = std::experimental::filesystem; void test01() { + bool test __attribute__((unused)) = false; + fs::path dot("."); fs::path cwd = fs::current_path(); std::error_code ec; @@ -39,6 +41,8 @@ test01() void test02() { + bool test __attribute__((unused)) = false; + auto oldwd = fs::current_path(); auto tmpdir = fs::temp_directory_path(); current_path(tmpdir); diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/exists.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/exists.cc index 0f1e5aa..dba4a6f 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/exists.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/exists.cc @@ -20,32 +20,37 @@ #include <experimental/filesystem> #include <testsuite_hooks.h> +#include <testsuite_fs.h> using std::experimental::filesystem::path; void test01() { + bool test __attribute__((unused)) = false; + VERIFY( exists(path{"/"}) ); VERIFY( exists(path{"/."}) ); VERIFY( exists(path{"."}) ); + VERIFY( exists(path{".."}) ); + VERIFY( exists(std::experimental::filesystem::current_path()) ); } void test02() { - path rel{"xXxXx"}; - while (exists(rel)) - rel /= "x"; + bool test __attribute__((unused)) = false; + + path rel = __gnu_test::nonexistent_path(); VERIFY( !exists(rel) ); } void test03() { - path abs{"/xXxXx"}; - while (exists(abs)) - abs /= "x"; + bool test __attribute__((unused)) = false; + + path abs = absolute(__gnu_test::nonexistent_path()); VERIFY( !exists(abs) ); } diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/file_size.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/file_size.cc index 04fa7bb..7603064 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/file_size.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/file_size.cc @@ -27,6 +27,8 @@ namespace fs = std::experimental::filesystem; void test01() { + bool test __attribute__((unused)) = false; + std::error_code ec; size_t size = fs::file_size(".", ec); VERIFY( ec == std::errc::is_a_directory ); @@ -45,6 +47,8 @@ test01() void test02() { + bool test __attribute__((unused)) = false; + fs::path p = __gnu_test::nonexistent_path(); std::error_code ec; diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/status.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/status.cc index 2c54494..0f1730d 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/status.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/status.cc @@ -27,6 +27,8 @@ namespace fs = std::experimental::filesystem; void test01() { + bool test __attribute__((unused)) = false; + std::error_code ec; fs::file_status st1 = fs::status(".", ec); VERIFY( !ec ); @@ -39,6 +41,8 @@ test01() void test02() { + bool test __attribute__((unused)) = false; + fs::path p = __gnu_test::nonexistent_path(); std::error_code ec; diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc index 2aacd1c..bd9b6ad 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc @@ -37,6 +37,8 @@ namespace fs = std::experimental::filesystem; void test01() { + bool test __attribute__((unused)) = false; + clean_env(); if (!fs::exists("/tmp")) @@ -53,6 +55,8 @@ test01() void test02() { + bool test __attribute__((unused)) = false; + clean_env(); if (::setenv("TMPDIR", __gnu_test::nonexistent_path().string().c_str(), 1)) diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/assign/assign.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/assign/assign.cc index 6fd24a7..fe4f96c 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/path/assign/assign.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/assign/assign.cc @@ -36,6 +36,7 @@ test01() p2 = s.c_str(); compare_paths(p0, p2); +#if _GLIBCXX_USE_WCHAR_T std::wstring ws(s.begin(), s.end()); p3 = ws; @@ -43,6 +44,7 @@ test01() p4 = ws.c_str(); compare_paths(p0, p4); +#endif } } @@ -65,6 +67,7 @@ test02() p4.assign( s.c_str(), s.c_str() + s.size() ); compare_paths(p0, p4); +#if _GLIBCXX_USE_WCHAR_T std::wstring ws(s.begin(), s.end()); p5.assign(ws); @@ -78,6 +81,7 @@ test02() p8.assign( ws.c_str(), ws.c_str() + ws.size() ); compare_paths(p0, p8); +#endif } } diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/concat/strings.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/concat/strings.cc index e75e790..61ef7e4 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/path/concat/strings.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/concat/strings.cc @@ -35,7 +35,11 @@ test01() VERIFY( p.filename() == "foobar" ); p += '/'; VERIFY( p.parent_path() == "/foobar" && p.filename() == "." ); +#if _GLIBCXX_USE_WCHAR_T p += L"baz.txt"; +#else + p += "baz.txt"; +#endif VERIFY( p.filename() == "baz.txt" ); p.concat("/dir/"); VERIFY( p.parent_path() == "/foobar/baz.txt/dir" && p.filename() == "." ); diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc index 03e5085..2e892291 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/path/construct/range.cc @@ -37,19 +37,22 @@ test01() path p3( s.c_str() ); path p4( s.c_str(), s.c_str() + s.size() ); + compare_paths(p1, p2); + compare_paths(p1, p3); + compare_paths(p1, p4); + +#if _GLIBCXX_USE_WCHAR_T std::wstring ws(s.begin(), s.end()); path p5 = ws; path p6( ws.begin(), ws.end() ); path p7( ws.c_str() ); path p8( ws.c_str(), ws.c_str() + ws.size() ); - compare_paths(p1, p2); - compare_paths(p1, p3); - compare_paths(p1, p4); compare_paths(p1, p5); compare_paths(p1, p6); compare_paths(p1, p7); compare_paths(p1, p8); +#endif } } diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/factory/TODO b/libstdc++-v3/testsuite/experimental/filesystem/path/factory/TODO deleted file mode 100644 index e69de29..0000000 diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/io/TODO b/libstdc++-v3/testsuite/experimental/filesystem/path/io/TODO diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/io/TODO b/libstdc++-v3/testsuite/experimental/filesystem/path/io/TODO deleted file mode 100644 index e69de29..0000000 diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/native/TODO b/libstdc++-v3/testsuite/experimental/filesystem/path/native/TODO