This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Backport C++ Filesystem TS fixes to gcc-5-branch


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]