This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[patch] Backport C++ Filesystem TS fixes to gcc-5-branch
- From: Jonathan Wakely <jwakely at redhat dot com>
- To: libstdc++ at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Wed, 7 Oct 2015 22:02:25 +0100
- Subject: [patch] Backport C++ Filesystem TS fixes to gcc-5-branch
- Authentication-results: sourceware.org; auth=none
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 <jwakely@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