1 // Copyright (C) 2018-2019 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library.  This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3.  If not see
16 // <http://www.gnu.org/licenses/>.
17 
18 // { dg-options "-std=gnu++17" }
19 // { dg-do run { target c++17 } }
20 // { dg-require-filesystem-ts "" }
21 
22 #include <filesystem>
23 #include <testsuite_hooks.h>
24 
25 using std::filesystem::filesystem_error;
26 
27 // The COW std::string does not have noexcept copies, because copying a
28 // "leaked" string can throw (and for fully-dynamic strings, copying the
29 // empty rep can also throw).
30 // That's OK, because we know that the std::string in the std::runtime_error
31 // or std::logic_error base class won't be leaked (and usually won't be empty).
32 // The is_nothrow_xxx type traits don't know that though, so we can only
33 // check them for the cxx11 ABI, which uses __cow_string, which has noexcept
34 // copies.
35 #if _GLIBCXX_USE_CXX11_ABI
36 // PR libstdc++/83306
37 static_assert(std::is_nothrow_copy_constructible_v<filesystem_error>);
38 static_assert(std::is_nothrow_copy_assignable_v<filesystem_error>);
39 #endif
40 
41 void
test01()42 test01()
43 {
44   const char* const str = "error test";
45   const std::error_code ec = make_error_code(std::errc::is_a_directory);
46   const filesystem_error e1(str, ec);
47   auto e2 = e1;
48   VERIFY( e2.path1().empty() );
49   VERIFY( e2.path2().empty() );
50   VERIFY( std::string_view(e2.what()).find(str) != std::string_view::npos );
51   VERIFY( e2.code() == ec );
52 
53   const filesystem_error e3(str, "test/path/one", ec);
54   auto e4 = e3;
55   VERIFY( e4.path1() == "test/path/one" );
56   VERIFY( e4.path2().empty() );
57   VERIFY( std::string_view(e4.what()).find(str) != std::string_view::npos );
58   VERIFY( e2.code() == ec );
59 
60   const filesystem_error e5(str, "test/path/one", "/test/path/two", ec);
61   auto e6 = e5;
62   VERIFY( e6.path1() == "test/path/one" );
63   VERIFY( e6.path2() == "/test/path/two" );
64   VERIFY( std::string_view(e6.what()).find(str) != std::string_view::npos );
65   VERIFY( e2.code() == ec );
66 }
67 
68 void
test02()69 test02()
70 {
71   const char* const str = "error test";
72   const std::error_code ec = make_error_code(std::errc::is_a_directory);
73   const filesystem_error e1(str, ec);
74   filesystem_error e2("", {});
75   e2 = e1;
76   VERIFY( e2.path1().empty() );
77   VERIFY( e2.path2().empty() );
78   VERIFY( std::string_view(e2.what()).find(str) != std::string_view::npos );
79   VERIFY( e2.code() == ec );
80 
81   const filesystem_error e3(str, "test/path/one", ec);
82   filesystem_error e4("", {});
83   e4 = e3;
84   VERIFY( e4.path1() == "test/path/one" );
85   VERIFY( e4.path2().empty() );
86   VERIFY( std::string_view(e4.what()).find(str) != std::string_view::npos );
87   VERIFY( e2.code() == ec );
88 
89   const filesystem_error e5(str, "test/path/one", "/test/path/two", ec);
90   filesystem_error e6("", {});
91   e6 = e5;
92   VERIFY( e6.path1() == "test/path/one" );
93   VERIFY( e6.path2() == "/test/path/two" );
94   VERIFY( std::string_view(e6.what()).find(str) != std::string_view::npos );
95   VERIFY( e2.code() == ec );
96 }
97 
98 void
test03()99 test03()
100 {
101   filesystem_error e("test", std::error_code());
102   VERIFY( e.path1().empty() );
103   VERIFY( e.path2().empty() );
104   auto e2 = std::move(e);
105   // Observers must still be usable on moved-from object:
106   VERIFY( e.path1().empty() );
107   VERIFY( e.path2().empty() );
108   VERIFY( e.what() != nullptr );
109   e2 = std::move(e);
110   VERIFY( e.path1().empty() );
111   VERIFY( e.path2().empty() );
112   VERIFY( e.what() != nullptr );
113 }
114 
115 int
main()116 main()
117 {
118   test01();
119   test02();
120   test03();
121 }
122