Implement filesystem_error::what() and improve reporting.

This patch implements the `what()` for filesystem errors. The message
includes the 'what_arg', any paths that were specified, and the
error code message.

Additionally this patch refactors how errors are created, making it easier
to report them correctly.

llvm-svn: 337664
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 9158bfd32ebd457476bc367707fcf391ca0520f1
diff --git a/include/experimental/filesystem b/include/experimental/filesystem
index 2d2c117..2ed3eec 100644
--- a/include/experimental/filesystem
+++ b/include/experimental/filesystem
@@ -1265,40 +1265,51 @@
     _LIBCPP_INLINE_VISIBILITY
     filesystem_error(const string& __what, error_code __ec)
         : system_error(__ec, __what),
-          __paths_(make_shared<_Storage>(path(), path()))
-    {}
+          __storage_(make_shared<_Storage>(path(), path())) {
+      __create_what(0);
+    }
 
     _LIBCPP_INLINE_VISIBILITY
     filesystem_error(const string& __what, const path& __p1, error_code __ec)
         : system_error(__ec, __what),
-        __paths_(make_shared<_Storage>(__p1, path()))
-    {}
+          __storage_(make_shared<_Storage>(__p1, path())) {
+      __create_what(1);
+    }
 
     _LIBCPP_INLINE_VISIBILITY
     filesystem_error(const string& __what, const path& __p1, const path& __p2,
                      error_code __ec)
         : system_error(__ec, __what),
-          __paths_(make_shared<_Storage>(__p1, __p2))
-    {}
-
-    _LIBCPP_INLINE_VISIBILITY
-    const path& path1() const _NOEXCEPT {
-        return __paths_->first;
+          __storage_(make_shared<_Storage>(__p1, __p2)) {
+      __create_what(2);
     }
 
     _LIBCPP_INLINE_VISIBILITY
-    const path& path2() const _NOEXCEPT {
-        return __paths_->second;
-    }
+    const path& path1() const _NOEXCEPT { return __storage_->__p1_; }
+
+    _LIBCPP_INLINE_VISIBILITY
+    const path& path2() const _NOEXCEPT { return __storage_->__p2_; }
 
     ~filesystem_error() override; // key function
 
-    // TODO(ericwf): Create a custom error message.
-    //const char* what() const _NOEXCEPT;
+    _LIBCPP_INLINE_VISIBILITY
+    const char* what() const _NOEXCEPT override {
+      return __storage_->__what_.c_str();
+    }
 
-private:
-    typedef pair<path, path> _Storage;
-    shared_ptr<_Storage> __paths_;
+    _LIBCPP_FUNC_VIS
+    void __create_what(int __num_paths);
+
+  private:
+    struct _Storage {
+      _LIBCPP_INLINE_VISIBILITY
+      _Storage(const path& __p1, const path& __p2) : __p1_(__p1), __p2_(__p2) {}
+
+      path __p1_;
+      path __p2_;
+      string __what_;
+    };
+    shared_ptr<_Storage> __storage_;
 };
 
 template <class... _Args>
@@ -1315,7 +1326,6 @@
 }
 #endif
 
-
 // operational functions
 
 _LIBCPP_FUNC_VIS
@@ -2226,12 +2236,13 @@
         return;
       }
       if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
-        __throw_filesystem_error(__msg, __p_, _Path{}, __ec);
+        __throw_filesystem_error(__msg, __p_, __ec);
     }
 
     _LIBCPP_INLINE_VISIBILITY
     void __refresh(error_code* __ec = nullptr) {
-      __handle_error("refresh", __ec, __do_refresh(), /*allow_dne*/ true);
+      __handle_error("in directory_entry::refresh", __ec, __do_refresh(),
+                     /*allow_dne*/ true);
     }
 
     _LIBCPP_INLINE_VISIBILITY
@@ -2322,11 +2333,11 @@
       case _RefreshNonSymlink: {
         error_code __m_ec;
         file_status __st(__get_ft(&__m_ec));
-        __handle_error("directory_entry::file_size", __ec, __m_ec);
+        __handle_error("in directory_entry::file_size", __ec, __m_ec);
         if (_VSTD_FS::exists(__st) && !_VSTD_FS::is_regular_file(__st)) {
           errc __err_kind = _VSTD_FS::is_directory(__st) ? errc::is_a_directory
                                                          : errc::not_supported;
-          __handle_error("directory_entry::file_size", __ec,
+          __handle_error("in directory_entry::file_size", __ec,
                          make_error_code(__err_kind));
         }
         return __data_.__size_;
@@ -2347,7 +2358,7 @@
       case _RefreshNonSymlink: {
         error_code __m_ec;
         (void)__get_ft(&__m_ec);
-        __handle_error("directory_entry::hard_link_count", __ec, __m_ec);
+        __handle_error("in directory_entry::hard_link_count", __ec, __m_ec);
         return __data_.__nlink_;
       }
       }
@@ -2366,10 +2377,10 @@
       case _RefreshNonSymlink: {
         error_code __m_ec;
         file_status __st(__get_ft(&__m_ec));
-        __handle_error("directory_entry::last_write_time", __ec, __m_ec);
+        __handle_error("in directory_entry::last_write_time", __ec, __m_ec);
         if (_VSTD_FS::exists(__st) &&
             __data_.__write_time_ == file_time_type::min())
-          __handle_error("directory_entry::last_write_time", __ec,
+          __handle_error("in directory_entry::last_write_time", __ec,
                          make_error_code(errc::value_too_large));
         return __data_.__write_time_;
       }