From: Jonathan Wakely Date: Sun, 6 Jan 2019 22:34:29 +0000 (+0000) Subject: PR libstdc++/86756 add std::filesystem::path to libstdc++.so X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2b5225352e9267152dc714e256576563a949a8f4;p=gcc.git PR libstdc++/86756 add std::filesystem::path to libstdc++.so Move the C++17 std::filesystem::path definitions from the libstdc++fs.a archive to the main libstdc++ library. The path classes do not depend on any OS functions, so can be defined unconditionally on all targets (rather than depending on --enable-libstdcxx-filesystem-ts). The tests should pass on all targets too. PR libstdc++/86756 * config/abi/pre/gnu.ver (GLIBCXX_3.4): Make various patterns for typeinfo and vtables less greedy. (GLIBCXX_3.4.26): Export symbols for std::filesystem::path. * src/c++17/Makefile.am: Add fs_path.cc and cow-fs_path.cc. * src/c++17/Makefile.in: Regenerate. * src/c++17/cow-fs_path.cc: Move src/filesystem/cow-std-path.cc to here, and change name of included file. * src/c++17/fs_path.cc: Move src/filesystem/std-path.cc to here. * src/filesystem/Makefile.am: Remove std-path.cc and cow-std-path.cc from sources. * src/filesystem/Makefile.in: Regenerate. * src/filesystem/cow-std-path.cc: Move to src/c++17/cow-fs_path.cc. * src/filesystem/std-path.cc: Move to src/c++17/fs_path.cc. * testsuite/27_io/filesystem/path/append/path.cc: Remove -lstdc++fs from dg-options and remove dg-require-filesystem-ts. * testsuite/27_io/filesystem/path/append/source.cc: Likewise. * testsuite/27_io/filesystem/path/assign/assign.cc: Likewise. * testsuite/27_io/filesystem/path/assign/copy.cc: Likewise. * testsuite/27_io/filesystem/path/compare/compare.cc: Likewise. * testsuite/27_io/filesystem/path/compare/lwg2936.cc: Likewise. * testsuite/27_io/filesystem/path/compare/path.cc: Likewise. * testsuite/27_io/filesystem/path/compare/strings.cc: Likewise. * testsuite/27_io/filesystem/path/concat/path.cc: Likewise. * testsuite/27_io/filesystem/path/concat/strings.cc: Likewise. * testsuite/27_io/filesystem/path/construct/80762.cc: Likewise. * testsuite/27_io/filesystem/path/construct/copy.cc: Likewise. * testsuite/27_io/filesystem/path/construct/default.cc: Likewise. * testsuite/27_io/filesystem/path/construct/format.cc: Likewise. * testsuite/27_io/filesystem/path/construct/locale.cc: Likewise. * testsuite/27_io/filesystem/path/construct/range.cc: Likewise. * testsuite/27_io/filesystem/path/construct/string_view.cc: Likewise. * testsuite/27_io/filesystem/path/decompose/extension.cc: Likewise. * testsuite/27_io/filesystem/path/decompose/filename.cc: Likewise. * testsuite/27_io/filesystem/path/decompose/parent_path.cc: Likewise. * testsuite/27_io/filesystem/path/decompose/relative_path.cc: Likewise. * testsuite/27_io/filesystem/path/decompose/root_directory.cc: Likewise. * testsuite/27_io/filesystem/path/decompose/root_name.cc: Likewise. * testsuite/27_io/filesystem/path/decompose/root_path.cc: Likewise. * testsuite/27_io/filesystem/path/decompose/stem.cc: Likewise. * testsuite/27_io/filesystem/path/generation/normal.cc: Likewise. * testsuite/27_io/filesystem/path/generation/normal2.cc: Likewise. * testsuite/27_io/filesystem/path/generation/proximate.cc: Likewise. * testsuite/27_io/filesystem/path/generation/relative.cc: Likewise. * testsuite/27_io/filesystem/path/generic/generic_string.cc: Likewise. * testsuite/27_io/filesystem/path/itr/components.cc: Likewise. * testsuite/27_io/filesystem/path/itr/traversal.cc: Likewise. * testsuite/27_io/filesystem/path/modifiers/clear.cc: Likewise. * testsuite/27_io/filesystem/path/modifiers/make_preferred.cc: Likewise. * testsuite/27_io/filesystem/path/modifiers/remove_filename.cc: Likewise. * testsuite/27_io/filesystem/path/modifiers/replace_extension.cc: Likewise. * testsuite/27_io/filesystem/path/modifiers/replace_filename.cc: Likewise. * testsuite/27_io/filesystem/path/modifiers/swap.cc: Likewise. * testsuite/27_io/filesystem/path/native/string.cc: Likewise. * testsuite/27_io/filesystem/path/nonmember/append.cc: Likewise. * testsuite/27_io/filesystem/path/nonmember/hash_value.cc: Likewise. * testsuite/27_io/filesystem/path/query/empty.cc: Likewise. * testsuite/27_io/filesystem/path/query/has_extension.cc: Likewise. * testsuite/27_io/filesystem/path/query/has_filename.cc: Likewise. * testsuite/27_io/filesystem/path/query/has_parent_path.cc: Likewise. * testsuite/27_io/filesystem/path/query/has_relative_path.cc: Likewise. * testsuite/27_io/filesystem/path/query/has_root_directory.cc: Likewise. * testsuite/27_io/filesystem/path/query/has_root_name.cc: Likewise. * testsuite/27_io/filesystem/path/query/has_root_path.cc: Likewise. * testsuite/27_io/filesystem/path/query/has_stem.cc: Likewise. * testsuite/27_io/filesystem/path/query/is_absolute.cc: Likewise. * testsuite/27_io/filesystem/path/query/is_relative.cc: Likewise. From-SVN: r267615 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index fe1643d69cc..dd893977340 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,79 @@ 2019-01-06 Jonathan Wakely + PR libstdc++/86756 + * config/abi/pre/gnu.ver (GLIBCXX_3.4): Make various patterns for + typeinfo and vtables less greedy. + (GLIBCXX_3.4.26): Export symbols for std::filesystem::path. + * src/c++17/Makefile.am: Add fs_path.cc and cow-fs_path.cc. + * src/c++17/Makefile.in: Regenerate. + * src/c++17/cow-fs_path.cc: Move src/filesystem/cow-std-path.cc to + here, and change name of included file. + * src/c++17/fs_path.cc: Move src/filesystem/std-path.cc to here. + * src/filesystem/Makefile.am: Remove std-path.cc and cow-std-path.cc + from sources. + * src/filesystem/Makefile.in: Regenerate. + * src/filesystem/cow-std-path.cc: Move to src/c++17/cow-fs_path.cc. + * src/filesystem/std-path.cc: Move to src/c++17/fs_path.cc. + * testsuite/27_io/filesystem/path/append/path.cc: Remove -lstdc++fs + from dg-options and remove dg-require-filesystem-ts. + * testsuite/27_io/filesystem/path/append/source.cc: Likewise. + * testsuite/27_io/filesystem/path/assign/assign.cc: Likewise. + * testsuite/27_io/filesystem/path/assign/copy.cc: Likewise. + * testsuite/27_io/filesystem/path/compare/compare.cc: Likewise. + * testsuite/27_io/filesystem/path/compare/lwg2936.cc: Likewise. + * testsuite/27_io/filesystem/path/compare/path.cc: Likewise. + * testsuite/27_io/filesystem/path/compare/strings.cc: Likewise. + * testsuite/27_io/filesystem/path/concat/path.cc: Likewise. + * testsuite/27_io/filesystem/path/concat/strings.cc: Likewise. + * testsuite/27_io/filesystem/path/construct/80762.cc: Likewise. + * testsuite/27_io/filesystem/path/construct/copy.cc: Likewise. + * testsuite/27_io/filesystem/path/construct/default.cc: Likewise. + * testsuite/27_io/filesystem/path/construct/format.cc: Likewise. + * testsuite/27_io/filesystem/path/construct/locale.cc: Likewise. + * testsuite/27_io/filesystem/path/construct/range.cc: Likewise. + * testsuite/27_io/filesystem/path/construct/string_view.cc: Likewise. + * testsuite/27_io/filesystem/path/decompose/extension.cc: Likewise. + * testsuite/27_io/filesystem/path/decompose/filename.cc: Likewise. + * testsuite/27_io/filesystem/path/decompose/parent_path.cc: Likewise. + * testsuite/27_io/filesystem/path/decompose/relative_path.cc: Likewise. + * testsuite/27_io/filesystem/path/decompose/root_directory.cc: + Likewise. + * testsuite/27_io/filesystem/path/decompose/root_name.cc: Likewise. + * testsuite/27_io/filesystem/path/decompose/root_path.cc: Likewise. + * testsuite/27_io/filesystem/path/decompose/stem.cc: Likewise. + * testsuite/27_io/filesystem/path/generation/normal.cc: Likewise. + * testsuite/27_io/filesystem/path/generation/normal2.cc: Likewise. + * testsuite/27_io/filesystem/path/generation/proximate.cc: Likewise. + * testsuite/27_io/filesystem/path/generation/relative.cc: Likewise. + * testsuite/27_io/filesystem/path/generic/generic_string.cc: Likewise. + * testsuite/27_io/filesystem/path/itr/components.cc: Likewise. + * testsuite/27_io/filesystem/path/itr/traversal.cc: Likewise. + * testsuite/27_io/filesystem/path/modifiers/clear.cc: Likewise. + * testsuite/27_io/filesystem/path/modifiers/make_preferred.cc: + Likewise. + * testsuite/27_io/filesystem/path/modifiers/remove_filename.cc: + Likewise. + * testsuite/27_io/filesystem/path/modifiers/replace_extension.cc: + Likewise. + * testsuite/27_io/filesystem/path/modifiers/replace_filename.cc: + Likewise. + * testsuite/27_io/filesystem/path/modifiers/swap.cc: Likewise. + * testsuite/27_io/filesystem/path/native/string.cc: Likewise. + * testsuite/27_io/filesystem/path/nonmember/append.cc: Likewise. + * testsuite/27_io/filesystem/path/nonmember/hash_value.cc: Likewise. + * testsuite/27_io/filesystem/path/query/empty.cc: Likewise. + * testsuite/27_io/filesystem/path/query/has_extension.cc: Likewise. + * testsuite/27_io/filesystem/path/query/has_filename.cc: Likewise. + * testsuite/27_io/filesystem/path/query/has_parent_path.cc: Likewise. + * testsuite/27_io/filesystem/path/query/has_relative_path.cc: Likewise. + * testsuite/27_io/filesystem/path/query/has_root_directory.cc: + Likewise. + * testsuite/27_io/filesystem/path/query/has_root_name.cc: Likewise. + * testsuite/27_io/filesystem/path/query/has_root_path.cc: Likewise. + * testsuite/27_io/filesystem/path/query/has_stem.cc: Likewise. + * testsuite/27_io/filesystem/path/query/is_absolute.cc: Likewise. + * testsuite/27_io/filesystem/path/query/is_relative.cc: Likewise. + PR libstdc++/87431 * include/std/variant (_Variant_storage::_M_valid): Check is_trivially_copyable instead of is_scalar. diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 6c18caa6d8a..f83d2b1cca9 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -767,19 +767,24 @@ GLIBCXX_3.4 { _ZTVSt18basic_stringstreamI*; _ZTVSt19basic_istringstreamI*; _ZTVSt19basic_ostringstreamI*; - _ZTVSt[0-9][0-9][c-d]*; - _ZTVSt[0-9][0-9][g-k]*; + _ZTVSt10ctype_base; + _ZTVSt12codecvt_base; + _ZTVSt12ctype_bynameI[cw]E; + _ZTVSt14co*_bynameI[cw]*; + _ZTVSt12domain_error; + _ZTVSt10istrstream; + _ZTVSt16invalid_argument; _ZTVSt11logic_error; _ZTVSt12length_error; -# _ZTVSt[0-9][0-9][m-q]*; - _ZTVSt[0-9][0-9][m]*; - _ZTVSt[0-9][0-9]n[^e]*; - _ZTVSt[0-9][0-9][o-q]*; + _ZTVSt1[07]money*; + _ZTVSt1[35]messages*; + _ZTVSt15numpunct_bynameI[cw]E; + _ZTVSt1[024]o*; _ZTVSt11range_error; _ZTVSt13runtime_error; - _ZTVSt[0-9][0-9][t-z]*; - _ZTVSt[0-9][0-9]e[^r]*; - _ZTVSt[0-9][0-9]s[^y]*; + _ZTVSt12strstreambuf; + _ZTVSt15time*; + _ZTVSt15underflow_error; _ZTVSt11__timepunctI[cw]E; _ZTVSt23__codecvt_abstract_baseI[cw]c11__mbstate_tE; @@ -821,19 +826,24 @@ GLIBCXX_3.4 { _ZTISt18basic_stringstreamI*; _ZTISt19basic_istringstreamI*; _ZTISt19basic_ostringstreamI*; - _ZTISt[0-9][0-9][c-d]*; - _ZTISt[0-9][0-9][g-k]*; + _ZTISt10ctype_base; + _ZTISt12codecvt_base; + _ZTISt12ctype_bynameI[cw]E; + _ZTISt14co*_bynameI[cw]*; + _ZTISt12domain_error; + _ZTISt10istrstream; + _ZTISt16invalid_argument; _ZTISt11logic_error; _ZTISt12length_error; -# _ZTISt[0-9][0-9][m-q]*; - _ZTISt[0-9][0-9][m]*; - _ZTISt[0-9][0-9]n[^e]*; - _ZTISt[0-9][0-9][o-q]*; + _ZTISt1[07]money*; + _ZTISt1[35]messages*; + _ZTISt15numpunct_bynameI[cw]E; + _ZTISt1[024]o*; _ZTISt11range_error; _ZTISt13runtime_error; - _ZTISt[0-9][0-9][t-z]*; - _ZTISt[0-9][0-9]e[^r]*; - _ZTISt[0-9][0-9]s[^y]*; + _ZTISt12strstreambuf; + _ZTISt15time*; + _ZTISt15underflow_error; _ZTISt11__timepunctI[cw]E; _ZTISt10__num_base; _ZTISt21__ctype_abstract_baseI[cw]E; @@ -869,19 +879,24 @@ GLIBCXX_3.4 { _ZTSSt18basic_stringstreamI*; _ZTSSt19basic_istringstreamI*; _ZTSSt19basic_ostringstreamI*; - _ZTSSt[0-9][0-9][c-d]*; - _ZTSSt[0-9][0-9][g-k]*; + _ZTSSt10ctype_base; + _ZTSSt12codecvt_base; + _ZTSSt12ctype_bynameI[cw]E; + _ZTSSt14co*_bynameI[cw]*; + _ZTSSt12domain_error; + _ZTSSt10istrstream; + _ZTSSt16invalid_argument; _ZTSSt11logic_error; _ZTSSt12length_error; -# _ZTSSt[0-9][0-9][m-q]*; - _ZTSSt[0-9][0-9][m]*; - _ZTSSt[0-9][0-9]n[^e]*; - _ZTSSt[0-9][0-9][o-q]*; + _ZTSSt1[07]money*; + _ZTSSt1[35]messages*; + _ZTSSt15numpunct_bynameI[cw]E; + _ZTSSt1[024]o*; _ZTSSt11range_error; _ZTSSt13runtime_error; - _ZTSSt[0-9][0-9][t-z]*; - _ZTSSt[0-9][0-9]e[^r]*; - _ZTSSt[0-9][0-9]s[^y]*; + _ZTSSt12strstreambuf; + _ZTSSt15time*; + _ZTSSt15underflow_error; _ZTSSt11__timepunctI[cw]E; _ZTSSt10__num_base; @@ -2099,6 +2114,59 @@ GLIBCXX_3.4.26 { _ZNSbIwSt11char_traitsIwESaIwEEC[12]ENS2_12__sv_wrapperERKS1_; _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EEC[12]ENS4_12__sv_wrapperERKS3_; + # std::filesystem symbols + _ZNKSt10filesystem16filesystem_error4whatEv; + _ZNKSt10filesystem16filesystem_error5path[12]Ev; + _ZNKSt10filesystem4path1[1-9][hlpr]*Ev; + _ZNKSt10filesystem4path17_M_find_extensionEv; + _ZNKSt10filesystem4path1[89]lexically_*ERKS0_; + _ZNKSt10filesystem4path5_List13_Impl_deleterclEPNS1_5_ImplE; + _ZNKSt10filesystem4path5_List3endEv; + _ZNKSt10filesystem4path5_List5beginEv; + _ZNKSt10filesystem4path7compareERKS0_; + _ZNKSt10filesystem4path7compareESt17basic_string_viewIcSt11char_traitsIcEE; + _ZNKSt10filesystem4path9root_*Ev; + _ZNSt10filesystem10hash_valueERKNS_4pathE; + _ZNSt10filesystem16filesystem_errorC[12]E*; + _ZNSt10filesystem16filesystem_errorD[012]Ev; + _ZNSt10filesystem4path14_M_split_cmptsEv; + _ZNSt10filesystem4path14_S_convert_locEPKcS2_RKSt6locale; + _ZNSt10filesystem4path1[567]re*; + _ZNSt10filesystem4path5_ListC1ERKS1_; + _ZNSt10filesystem4path5_ListC1Ev; + _ZNSt10filesystem4path9_M_appendESt17basic_string_viewIcSt11char_traitsIcEE; + _ZNSt10filesystem4path9_M_concatESt17basic_string_viewIcSt11char_traitsIcEE; + _ZNSt10filesystem4pathaSERKS0_; + _ZNSt10filesystem4pathdVERKS0_; + _ZNSt10filesystem4pathpLERKS0_; + _ZT[IV]NSt10filesystem16filesystem_errorE; + + _ZNKSt10filesystem7__cxx1116filesystem_error4whatEv; + _ZNKSt10filesystem7__cxx1116filesystem_error5path[12]Ev; + _ZNKSt10filesystem7__cxx114path1[1-9][hlpr]*Ev; + _ZNKSt10filesystem7__cxx114path17_M_find_extensionEv; + _ZNKSt10filesystem7__cxx114path1[89]lexically_*ERKS1_; + _ZNKSt10filesystem7__cxx114path5_List13_Impl_deleterclEPNS2_5_ImplE; + _ZNKSt10filesystem7__cxx114path5_List3endEv; + _ZNKSt10filesystem7__cxx114path5_List5beginEv; + _ZNKSt10filesystem7__cxx114path7compareERKS1_; + _ZNKSt10filesystem7__cxx114path7compareESt17basic_string_viewIcSt11char_traitsIcEE; + _ZNKSt10filesystem7__cxx114path9root_*Ev; + _ZNSt10filesystem7__cxx1110hash_valueERKNS0_4pathE; + _ZNSt10filesystem7__cxx1116filesystem_errorC[12]E*; + _ZNSt10filesystem7__cxx1116filesystem_errorD[012]Ev; + _ZNSt10filesystem7__cxx114path14_M_split_cmptsEv; + _ZNSt10filesystem7__cxx114path14_S_convert_locEPKcS3_RKSt6locale; + _ZNSt10filesystem7__cxx114path1[567]re*; + _ZNSt10filesystem7__cxx114path5_ListC1ERKS2_; + _ZNSt10filesystem7__cxx114path5_ListC1Ev; + _ZNSt10filesystem7__cxx114path9_M_appendESt17basic_string_viewIcSt11char_traitsIcEE; + _ZNSt10filesystem7__cxx114path9_M_concatESt17basic_string_viewIcSt11char_traitsIcEE; + _ZNSt10filesystem7__cxx114pathaSERKS1_; + _ZNSt10filesystem7__cxx114pathdVERKS1_; + _ZNSt10filesystem7__cxx114pathpLERKS1_; + _ZT[IV]NSt10filesystem7__cxx1116filesystem_errorE; + } GLIBCXX_3.4.25; # Symbols in the support library (libsupc++) have their own tag. diff --git a/libstdc++-v3/src/c++17/Makefile.am b/libstdc++-v3/src/c++17/Makefile.am index afa119eecb6..85883c33f2d 100644 --- a/libstdc++-v3/src/c++17/Makefile.am +++ b/libstdc++-v3/src/c++17/Makefile.am @@ -27,14 +27,12 @@ noinst_LTLIBRARIES = libc++17convenience.la headers = -sources = \ - memory_resource.cc \ - string-inst.cc - if ENABLE_DUAL_ABI extra_string_inst_sources = cow-string-inst.cc +extra_fs_sources = cow-fs_path.cc else extra_string_inst_sources = +extra_fs_sources = endif if ENABLE_EXTERN_TEMPLATE @@ -46,6 +44,12 @@ else inst_sources = endif +sources = \ + fs_path.cc \ + memory_resource.cc \ + string-inst.cc \ + $(extra_fs_sources) + vpath % $(top_srcdir)/src/c++17 libc__17convenience_la_SOURCES = $(sources) $(inst_sources) @@ -59,16 +63,12 @@ AM_CXXFLAGS = \ -std=gnu++17 \ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \ $(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \ - $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) + $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) \ + -fimplicit-templates AM_MAKEFLAGS = \ "gxx_include_dir=$(gxx_include_dir)" -memory_resource.lo: memory_resource.cc - $(LTCXXCOMPILE) -fimplicit-templates -c $< -o $@ -memory_resource.o: memory_resource.cc - $(CXXCOMPILE) -fimplicit-templates -c $< -o $@ - # Libtool notes # 1) In general, libtool expects an argument such as `--tag=CXX' when diff --git a/libstdc++-v3/src/c++17/Makefile.in b/libstdc++-v3/src/c++17/Makefile.in index 0657bdcf9d9..d76580f08aa 100644 --- a/libstdc++-v3/src/c++17/Makefile.in +++ b/libstdc++-v3/src/c++17/Makefile.in @@ -121,10 +121,12 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libc__17convenience_la_LIBADD = -am__objects_1 = memory_resource.lo string-inst.lo -@ENABLE_DUAL_ABI_TRUE@am__objects_2 = cow-string-inst.lo -@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_3 = $(am__objects_2) -am_libc__17convenience_la_OBJECTS = $(am__objects_1) $(am__objects_3) +@ENABLE_DUAL_ABI_TRUE@am__objects_1 = cow-fs_path.lo +am__objects_2 = fs_path.lo memory_resource.lo string-inst.lo \ + $(am__objects_1) +@ENABLE_DUAL_ABI_TRUE@am__objects_3 = cow-string-inst.lo +@ENABLE_EXTERN_TEMPLATE_TRUE@am__objects_4 = $(am__objects_3) +am_libc__17convenience_la_OBJECTS = $(am__objects_2) $(am__objects_4) libc__17convenience_la_OBJECTS = $(am_libc__17convenience_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -410,12 +412,10 @@ AM_CPPFLAGS = $(GLIBCXX_INCLUDES) $(CPPFLAGS) # Convenience library for C++17 runtime. noinst_LTLIBRARIES = libc++17convenience.la headers = -sources = \ - memory_resource.cc \ - string-inst.cc - @ENABLE_DUAL_ABI_FALSE@extra_string_inst_sources = @ENABLE_DUAL_ABI_TRUE@extra_string_inst_sources = cow-string-inst.cc +@ENABLE_DUAL_ABI_FALSE@extra_fs_sources = +@ENABLE_DUAL_ABI_TRUE@extra_fs_sources = cow-fs_path.cc # XTEMPLATE_FLAGS = @ENABLE_EXTERN_TEMPLATE_FALSE@inst_sources = @@ -423,6 +423,12 @@ sources = \ @ENABLE_EXTERN_TEMPLATE_TRUE@inst_sources = \ @ENABLE_EXTERN_TEMPLATE_TRUE@ $(extra_string_inst_sources) +sources = \ + fs_path.cc \ + memory_resource.cc \ + string-inst.cc \ + $(extra_fs_sources) + libc__17convenience_la_SOURCES = $(sources) $(inst_sources) # AM_CXXFLAGS needs to be in each subdirectory so that it can be @@ -434,7 +440,8 @@ AM_CXXFLAGS = \ -std=gnu++17 \ $(glibcxx_lt_pic_flag) $(glibcxx_compiler_shared_flag) \ $(XTEMPLATE_FLAGS) $(VTV_CXXFLAGS) \ - $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) + $(WARN_CXXFLAGS) $(OPTIMIZE_CXXFLAGS) $(CONFIG_CXXFLAGS) \ + -fimplicit-templates AM_MAKEFLAGS = \ "gxx_include_dir=$(gxx_include_dir)" @@ -732,11 +739,6 @@ uninstall-am: vpath % $(top_srcdir)/src/c++17 -memory_resource.lo: memory_resource.cc - $(LTCXXCOMPILE) -fimplicit-templates -c $< -o $@ -memory_resource.o: memory_resource.cc - $(CXXCOMPILE) -fimplicit-templates -c $< -o $@ - # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/libstdc++-v3/src/c++17/cow-fs_path.cc b/libstdc++-v3/src/c++17/cow-fs_path.cc new file mode 100644 index 00000000000..53539a6b806 --- /dev/null +++ b/libstdc++-v3/src/c++17/cow-fs_path.cc @@ -0,0 +1,26 @@ +// Class filesystem::path -*- C++ -*- + +// Copyright (C) 2015-2019 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 +// . + +#define _GLIBCXX_USE_CXX11_ABI 0 +#include "fs_path.cc" diff --git a/libstdc++-v3/src/c++17/fs_path.cc b/libstdc++-v3/src/c++17/fs_path.cc new file mode 100644 index 00000000000..34de52f3a0f --- /dev/null +++ b/libstdc++-v3/src/c++17/fs_path.cc @@ -0,0 +1,2007 @@ +// Class filesystem::path -*- C++ -*- + +// Copyright (C) 2014-2019 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 +// . + +#ifndef _GLIBCXX_USE_CXX11_ABI +# define _GLIBCXX_USE_CXX11_ABI 1 +#endif + +#ifdef __CYGWIN__ +// Interpret "//x" as a root-name, not root-dir + filename +# define SLASHSLASH_IS_ROOTNAME 1 +#endif + +#include +#include +#include + +namespace fs = std::filesystem; +using fs::path; + +static inline bool is_dir_sep(path::value_type ch) +{ +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return ch == L'/' || ch == path::preferred_separator; +#else + return ch == '/'; +#endif +} + +struct path::_Parser +{ + using string_view_type = std::basic_string_view; + + struct cmpt + { + string_view_type str; + _Type type = _Type::_Multi; + + bool valid() const { return type != _Type::_Multi; } + }; + + string_view_type input; + string_view_type::size_type pos = 0; + size_t origin; + _Type last_type = _Type::_Multi; + + _Parser(string_view_type s, size_t o = 0) : input(s), origin(o) { } + + pair root_path() noexcept + { + pos = 0; + pair root; + + const size_t len = input.size(); + + // look for root name or root directory + if (is_dir_sep(input[0])) + { +#if SLASHSLASH_IS_ROOTNAME + // look for root name, such as "//foo" + if (len > 2 && input[1] == input[0]) + { + if (!is_dir_sep(input[2])) + { + // got root name, find its end + pos = 3; + while (pos < len && !is_dir_sep(input[pos])) + ++pos; + root.first.str = input.substr(0, pos); + root.first.type = _Type::_Root_name; + + if (pos < len) // also got root directory + { + root.second.str = input.substr(pos, 1); + root.second.type = _Type::_Root_dir; + ++pos; + } + } + else + { + // got something like "///foo" which is just a root directory + // composed of multiple redundant directory separators + root.first.str = input.substr(0, 1); + root.first.type = _Type::_Root_dir; + pos += 2; + } + } + else +#endif + { + root.first.str = input.substr(0, 1); + root.first.type = _Type::_Root_dir; + ++pos; + } + // Find the start of the first filename + while (pos < len && is_dir_sep(input[pos])) + ++pos; + } +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + else if (len > 1 && input[1] == L':') + { + // got disk designator + root.first.str = input.substr(0, 2); + root.first.type = _Type::_Root_name; + if (len > 2 && is_dir_sep(input[2])) + { + root.second.str = input.substr(2, 1); + root.second.type = _Type::_Root_dir; + } + pos = input.find_first_not_of(L"/\\", 2); + } +#endif + + if (root.second.valid()) + last_type = root.second.type; + else + last_type = root.first.type; + + return root; + } + + cmpt next() noexcept + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + string_view_type sep = L"/\\"; +#else + char sep = '/'; +#endif + + const int last_pos = pos; + + cmpt f; + if (pos != input.npos) + { + pos = input.find_first_not_of(sep, pos); + if (pos != input.npos) + { + const auto end = input.find_first_of(sep, pos); + f.str = input.substr(pos, end - pos); + f.type = _Type::_Filename; + pos = end; + } + else if (last_type == _Type::_Filename + || (last_pos == 0 && !input.empty())) + { + // [fs.path.itr]/4 An empty element, if trailing non-root + // directory-separator present. + __glibcxx_assert(is_dir_sep(input.back())); + f.str = input.substr(input.length(), 0); + f.type = _Type::_Filename; + } + } + last_type = f.type; + return f; + } + + string_view_type::size_type + offset(const cmpt& c) const noexcept + { return origin + c.str.data() - input.data(); } +}; + +struct path::_List::_Impl +{ + using value_type = _Cmpt; + + _Impl(int cap) : _M_size(0), _M_capacity(cap) { } + + alignas(value_type) int _M_size; + int _M_capacity; + + using iterator = value_type*; + using const_iterator = const value_type*; + + iterator begin() { return reinterpret_cast(this + 1); } + iterator end() { return begin() + size(); } + + const_iterator begin() const + { return reinterpret_cast(this + 1); } + const_iterator end() const { return begin() + size(); } + + const value_type& front() const { return *begin(); } + const value_type& back() const { return end()[-1]; } + + int size() const { return _M_size; } + int capacity() const { return _M_capacity; } + bool empty() const { return _M_size == 0; } + + void clear() { std::destroy_n(begin(), _M_size); _M_size = 0; } + + void pop_back() + { + back().~_Cmpt(); + --_M_size; + } + + void _M_erase_from(const_iterator pos) + { + iterator first = begin() + (pos - begin()); + iterator last = end(); + std::destroy(first, last); + _M_size -= last - first; + } + + unique_ptr<_Impl, _Impl_deleter> copy() const + { + const auto n = size(); + void* p = ::operator new(sizeof(_Impl) + n * sizeof(value_type)); + unique_ptr<_Impl, _Impl_deleter> newptr(::new (p) _Impl{n}); + std::uninitialized_copy_n(begin(), n, newptr->begin()); + newptr->_M_size = n; + return newptr; + } + + // Clear the lowest two bits from the pointer (i.e. remove the _Type value) + static _Impl* notype(_Impl* p) + { + constexpr uintptr_t mask = ~(uintptr_t)0x3; + return reinterpret_cast<_Impl*>(reinterpret_cast(p) & mask); + } +}; + +void path::_List::_Impl_deleter::operator()(_Impl* p) const noexcept +{ + p = _Impl::notype(p); + if (p) + { + __glibcxx_assert(p->_M_size <= p->_M_capacity); + p->clear(); + ::operator delete(p, sizeof(*p) + p->_M_capacity * sizeof(value_type)); + } +} + +path::_List::_List() : _M_impl(reinterpret_cast<_Impl*>(_Type::_Filename)) { } + +path::_List::_List(const _List& other) +{ + if (!other.empty()) + _M_impl = other._M_impl->copy(); + else + type(other.type()); +} + +path::_List& +path::_List::operator=(const _List& other) +{ + if (!other.empty()) + { + // copy in-place if there is capacity + const int newsize = other._M_impl->size(); + auto impl = _Impl::notype(_M_impl.get()); + if (impl && impl->capacity() >= newsize) + { + const int oldsize = impl->_M_size; + auto to = impl->begin(); + auto from = other._M_impl->begin(); + const int minsize = std::min(newsize, oldsize); + for (int i = 0; i < minsize; ++i) + to[i]._M_pathname.reserve(from[i]._M_pathname.length()); + if (newsize > oldsize) + { + std::uninitialized_copy_n(to + oldsize, newsize - oldsize, + from + oldsize); + impl->_M_size = newsize; + } + else if (newsize < oldsize) + impl->_M_erase_from(impl->begin() + newsize); + std::copy_n(from, minsize, to); + type(_Type::_Multi); + } + else + _M_impl = other._M_impl->copy(); + } + else + { + clear(); + type(other.type()); + } + return *this; +} + +inline void +path::_List::type(_Type t) noexcept +{ + auto val = reinterpret_cast(_Impl::notype(_M_impl.release())); + _M_impl.reset(reinterpret_cast<_Impl*>(val | (unsigned char)t)); +} + +inline int +path::_List::size() const noexcept +{ + if (auto* ptr = _Impl::notype(_M_impl.get())) + return ptr->size(); + return 0; +} + +inline int +path::_List::capacity() const noexcept +{ + if (auto* ptr = _Impl::notype(_M_impl.get())) + return ptr->capacity(); + return 0; +} + +inline bool +path::_List::empty() const noexcept +{ + return size() == 0; +} + +inline auto +path::_List::begin() noexcept +-> iterator +{ + __glibcxx_assert(!empty()); + if (auto* ptr = _Impl::notype(_M_impl.get())) + return ptr->begin(); + return nullptr; +} + +inline auto +path::_List::end() noexcept +-> iterator +{ + __glibcxx_assert(!empty()); + if (auto* ptr = _Impl::notype(_M_impl.get())) + return ptr->end(); + return nullptr; +} + +auto +path::_List::begin() const noexcept +-> const_iterator +{ + __glibcxx_assert(!empty()); + if (auto* ptr = _Impl::notype(_M_impl.get())) + return ptr->begin(); + return nullptr; +} + +auto +path::_List::end() const noexcept +-> const_iterator +{ + __glibcxx_assert(!empty()); + if (auto* ptr = _Impl::notype(_M_impl.get())) + return ptr->end(); + return nullptr; +} + +inline auto +path::_List::front() noexcept +-> value_type& +{ + return *_M_impl->begin(); +} + +inline auto +path::_List::back() noexcept +-> value_type& +{ + return _M_impl->begin()[_M_impl->size() - 1]; +} + +inline auto +path::_List::front() const noexcept +-> const value_type& +{ + return *_M_impl->begin(); +} + +inline auto +path::_List::back() const noexcept +-> const value_type& +{ + return _M_impl->begin()[_M_impl->size() - 1]; +} + +inline void +path::_List::pop_back() +{ + __glibcxx_assert(size() > 0); + _M_impl->pop_back(); +} + +inline void +path::_List::_M_erase_from(const_iterator pos) +{ + _M_impl->_M_erase_from(pos); +} + +inline void +path::_List::clear() +{ + if (auto ptr = _Impl::notype(_M_impl.get())) + ptr->clear(); +} + +void +path::_List::reserve(int newcap, bool exact = false) +{ + // __glibcxx_assert(type() == _Type::_Multi); + + _Impl* curptr = _Impl::notype(_M_impl.get()); + + int curcap = curptr ? curptr->capacity() : 0; + + if (curcap < newcap) + { + if (!exact && newcap < int(1.5 * curcap)) + newcap = 1.5 * curcap; + + void* p = ::operator new(sizeof(_Impl) + newcap * sizeof(value_type)); + std::unique_ptr<_Impl, _Impl_deleter> newptr(::new(p) _Impl{newcap}); + const int cursize = curptr ? curptr->size() : 0; + if (cursize) + { + std::uninitialized_move_n(curptr->begin(), cursize, newptr->begin()); + newptr->_M_size = cursize; + } + std::swap(newptr, _M_impl); + } +} + +path& +path::operator=(const path& p) +{ + _M_pathname.reserve(p._M_pathname.length()); + _M_cmpts = p._M_cmpts; // might throw + _M_pathname = p._M_pathname; // won't throw because we reserved enough space + return *this; +} + +path& +path::operator/=(const path& __p) +{ +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + if (__p.is_absolute() + || (__p.has_root_name() && __p.root_name() != root_name())) + return operator=(__p); + + basic_string_view __lhs = _M_pathname; + bool __add_sep = false; + + if (__p.has_root_directory()) + { + // Remove any root directory and relative path + if (_M_type() != _Type::_Root_name) + { + if (!_M_cmpts.empty() + && _M_cmpts.front()._M_type() == _Type::_Root_name) + __lhs = _M_cmpts.front()._M_pathname; + else + __lhs = {}; + } + } + else if (has_filename() || (!has_root_directory() && is_absolute())) + __add_sep = true; + + basic_string_view __rhs = __p._M_pathname; + // Omit any root-name from the generic format pathname: + if (__p._M_type() == _Type::_Root_name) + __rhs = {}; + else if (!__p._M_cmpts.empty() + && __p._M_cmpts.front()._M_type() == _Type::_Root_name) + __rhs.remove_prefix(__p._M_cmpts.front()._M_pathname.size()); + + const size_t __len = __lhs.size() + (int)__add_sep + __rhs.size(); + const int __maxcmpts = _M_cmpts.size() + __p._M_cmpts.size(); + if (_M_pathname.capacity() < __len || _M_cmpts.capacity() < __maxcmpts) + { + // Construct new path and swap (strong exception-safety guarantee). + string_type __tmp; + __tmp.reserve(__len); + __tmp = __lhs; + if (__add_sep) + __tmp += preferred_separator; + __tmp += __rhs; + path __newp = std::move(__tmp); + swap(__newp); + } + else + { + _M_pathname = __lhs; + if (__add_sep) + _M_pathname += preferred_separator; + _M_pathname += __rhs; + __try + { + _M_split_cmpts(); + } + __catch (...) + { + __try + { + // try to restore original state + _M_pathname.resize(__lhs.length()); + _M_split_cmpts(); + } + __catch (...) + { + // give up, basic exception safety guarantee only: + clear(); + __throw_exception_again; + } + } + } +#else + // POSIX version is simpler than the specification in the standard, + // as any path with root-name or root-dir is absolute. + + if (__p.is_absolute() || this->empty()) + { + return operator=(__p); + } + + using string_view_type = basic_string_view; + + string_view_type sep; + if (has_filename()) + sep = { &preferred_separator, 1 }; // need to add a separator +#if SLASHSLASH_IS_ROOTNAME + else if (_M_type() == _Type::_Root_name) // root-name with no root-dir + sep = { &preferred_separator, 1 }; // need to add a separator +#endif + else if (__p.empty()) + return *this; // nothing to do + + const auto orig_pathlen = _M_pathname.length(); + const auto orig_size = _M_cmpts.size(); + const auto orig_type = _M_type(); + + int capacity = 0; + if (_M_type() == _Type::_Multi) + capacity += _M_cmpts.size(); + else if (!empty()) + capacity += 1; + if (__p._M_type() == _Type::_Multi) + capacity += __p._M_cmpts.size(); + else if (!__p.empty() || !sep.empty()) + capacity += 1; +#if SLASHSLASH_IS_ROOTNAME + if (orig_type == _Type::_Root_name) + ++capacity; // Need to insert root-directory after root-name +#endif + + if (orig_type == _Type::_Multi) + { + const int curcap = _M_cmpts._M_impl->capacity(); + if (capacity > curcap) + capacity = std::max(capacity, (int) (curcap * 1.5)); + } + + _M_pathname.reserve(_M_pathname.length() + sep.length() + + __p._M_pathname.length()); + + __try + { + _M_pathname += sep; + const auto basepos = _M_pathname.length(); + _M_pathname += __p.native(); + + _M_cmpts.type(_Type::_Multi); + _M_cmpts.reserve(capacity); + _Cmpt* output = _M_cmpts._M_impl->end(); + + if (orig_type == _Type::_Multi) + { + // Remove empty final component + if (_M_cmpts._M_impl->back().empty()) + { + _M_cmpts.pop_back(); + --output; + } + } + else if (orig_pathlen != 0) + { + // Create single component from original path + string_view_type s(_M_pathname.data(), orig_pathlen); + ::new(output++) _Cmpt(s, orig_type, 0); + ++_M_cmpts._M_impl->_M_size; +#if SLASHSLASH_IS_ROOTNAME + if (orig_type == _Type::_Root_name) + { + ::new(output++) _Cmpt(sep, _Type::_Root_dir, + orig_pathlen + sep.length()); + ++_M_cmpts._M_impl->_M_size; + } +#endif + } + + if (__p._M_type() == _Type::_Multi) + { + for (auto& c : *__p._M_cmpts._M_impl) + { + ::new(output++) _Cmpt(c._M_pathname, _Type::_Filename, + c._M_pos + basepos); + ++_M_cmpts._M_impl->_M_size; + } + } + else if (!__p.empty() || !sep.empty()) + { + __glibcxx_assert(__p._M_type() == _Type::_Filename); + ::new(output) _Cmpt(__p._M_pathname, __p._M_type(), basepos); + ++_M_cmpts._M_impl->_M_size; + } + } + __catch (...) + { + _M_pathname.resize(orig_pathlen); + if (orig_type == _Type::_Multi) + _M_cmpts._M_erase_from(_M_cmpts.begin() + orig_size); + else + _M_cmpts.clear(); + _M_cmpts.type(orig_type); + __throw_exception_again; + } +#endif + return *this; +} + +// [fs.path.append] +void +path::_M_append(basic_string_view s) +{ + _Parser parser(s); + auto root_path = parser.root_path(); + +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + bool is_absolute = root_path.second.type == _Type::_Root_dir; + bool has_root_name = root_path.first.type == _Type::_Root_name; + if (is_absolute || (has_root_name && root_path.first.str != root_name())) + { + operator=(s); + return; + } + + basic_string_view lhs = _M_pathname; + bool add_sep = false; + + bool has_root_directory = root_path.first.type == _Type::_Root_dir + || root_path.second.type == _Type::_Root_dir; + + if (has_root_directory) + { + // Remove any root directory and relative path + if (_M_type() != _Type::_Root_name) + { + if (!_M_cmpts.empty() + && _M_cmpts.front()._M_type() == _Type::_Root_name) + lhs = _M_cmpts.front()._M_pathname; + else + lhs = {}; + } + } + else if (has_filename() || (!has_root_directory && is_absolute)) + add_sep = true; + + basic_string_view rhs = s; + // Omit any root-name from the generic format pathname: + if (has_root_name) + rhs.remove_prefix(root_path.first.str.length()); + + // Construct new path and swap (strong exception-safety guarantee). + string_type tmp; + tmp.reserve(lhs.size() + (int)add_sep + rhs.size()); + tmp = lhs; + if (add_sep) + tmp += preferred_separator; + tmp += rhs; + path newp = std::move(tmp); + swap(newp); +#else + + bool is_absolute = root_path.first.type == _Type::_Root_dir + || root_path.second.type == _Type::_Root_dir; + if (is_absolute || this->empty()) + { + operator=(s); + return; + } + + const auto orig_pathlen = _M_pathname.length(); + const auto orig_size = _M_cmpts.size(); + const auto orig_type = _M_type(); + + basic_string_view sep; + if (has_filename()) + sep = { &preferred_separator, 1 }; // need to add a separator +#if SLASHSLASH_IS_ROOTNAME + else if (_M_type() == _Type::_Root_name) // root-name with no root-dir + sep = { &preferred_separator, 1 }; // need to add a separator +#endif + else if (s.empty()) + return; // nothing to do + + // Copy the input into _M_pathname: + _M_pathname += s; + _M_pathname.insert(orig_pathlen, sep); + // Update s to refer to the new copy (this ensures s is not a dangling + // reference to deallocated characters, in the case where it was referring + // into _M_pathname or a member of _M_cmpts). + s = _M_pathname; + const auto orig_pathname = s.substr(0, orig_pathlen); + s.remove_prefix(orig_pathlen + sep.length()); + + parser.input = s; // reset parser to use updated string view + const auto basepos = orig_pathname.length() + sep.length(); + parser.origin = basepos; + + std::array<_Parser::cmpt, 64> buf; + auto next = buf.begin(); + + int capacity = 0; + if (_M_type() == _Type::_Multi) + capacity += _M_cmpts.size(); + else if (!empty()) + capacity += 1; + + auto cmpt = parser.next(); + if (cmpt.valid()) + { + do + { + *next++ = cmpt; + cmpt = parser.next(); + } + while (cmpt.valid() && next != buf.end()); + + capacity += next - buf.begin(); + if (cmpt.valid()) // filled buffer before parsing whole input + { + ++capacity; + _Parser parser2(parser); + while (parser2.next().valid()) + ++capacity; + } + } + else if (!sep.empty()) + ++capacity; + +#if SLASHSLASH_IS_ROOTNAME + if (orig_type == _Type::_Root_name) + ++capacity; // Need to insert root-directory after root-name +#endif + + __try + { + _M_cmpts.type(_Type::_Multi); + _M_cmpts.reserve(capacity); + _Cmpt* output = _M_cmpts._M_impl->end(); + + if (orig_type == _Type::_Multi) + { + // Remove empty final component + if (_M_cmpts._M_impl->back().empty()) + { + _M_cmpts.pop_back(); + --output; + } + } + else if (orig_pathlen != 0) + { + // Create single component from original path + ::new(output++) _Cmpt(orig_pathname, orig_type, 0); + ++_M_cmpts._M_impl->_M_size; + +#if SLASHSLASH_IS_ROOTNAME + if (!sep.empty() && orig_type == _Type::_Root_name) + { + ::new(output++) _Cmpt(sep, _Type::_Root_dir, + orig_pathlen + sep.length()); + ++_M_cmpts._M_impl->_M_size; + } +#endif + } + + if (next != buf.begin()) + { + for (auto it = buf.begin(); it != next; ++it) + { + auto c = *it; + ::new(output++) _Cmpt(c.str, c.type, parser.offset(c)); + ++_M_cmpts._M_impl->_M_size; + } + while (cmpt.valid()) + { + ::new(output++) _Cmpt(cmpt.str, cmpt.type, parser.offset(cmpt)); + ++_M_cmpts._M_impl->_M_size; + cmpt = parser.next(); + } + } + else if (!sep.empty()) + { + // Empty filename at the end: + ::new(output) _Cmpt({}, _Type::_Filename, basepos); + ++_M_cmpts._M_impl->_M_size; + } + } + __catch (...) + { + _M_pathname.resize(orig_pathlen); + if (orig_type == _Type::_Multi) + _M_cmpts._M_erase_from(_M_cmpts.begin() + orig_size); + else + _M_cmpts.clear(); + _M_cmpts.type(orig_type); + __throw_exception_again; + } +#endif +} + +// [fs.path.concat] +path& +path::operator+=(const path& p) +{ + if (p.empty()) + return *this; + + if (this->empty()) + { + operator=(p); + return *this; + } + + const auto orig_pathlen = _M_pathname.length(); + const auto orig_type = _M_type(); + const auto orig_size = _M_cmpts.size(); + int orig_filenamelen = -1; + basic_string_view extra; + + // Ensure that '_M_pathname += p._M_pathname' won't throw: + _M_pathname.reserve(orig_pathlen + p._M_pathname.length()); + + _Cmpt c; + _Cmpt* it = nullptr; + _Cmpt* last = nullptr; + if (p._M_type() == _Type::_Multi) + { + it = p._M_cmpts._M_impl->begin(); + last = p._M_cmpts._M_impl->end(); + } + else + { + c = _Cmpt(p._M_pathname, p._M_type(), 0); + it = &c; + last = it + 1; + } + + if (it->_M_type() == _Type::_Filename) + { + // See if there's a filename or root-name at the end of the original path + // that we can add to. + if (_M_type() == _Type::_Filename +#if SLASHSLASH_IS_ROOTNAME + || _M_type() == _Type::_Root_name +#endif + ) + { + if (p._M_type() == _Type::_Filename) + { + // Simplest case where we just add the whole of p to the + // original path. + _M_pathname += p._M_pathname; + return *this; + } + // Only the first component of s should be appended, do so below: + extra = it->_M_pathname; + ++it; + } + else if (_M_type() == _Type::_Multi + && _M_cmpts.back()._M_type() == _Type::_Filename) + { + auto& back = _M_cmpts.back(); + if (p._M_type() == _Type::_Filename) + { + basic_string_view s = p._M_pathname; + back._M_pathname += s; + _M_pathname += s; + return *this; + } + + orig_filenamelen = back._M_pathname.length(); + back._M_pathname += it->_M_pathname; + extra = it->_M_pathname; + ++it; + } + } + else if (is_dir_sep(_M_pathname.back()) && _M_type() == _Type::_Multi + && _M_cmpts.back()._M_type() == _Type::_Filename) + orig_filenamelen = 0; // current path has empty filename at end + + int capacity = 0; + if (_M_type() == _Type::_Multi) + capacity += _M_cmpts.size(); + else + capacity += 1; + if (p._M_type() == _Type::_Multi) + capacity += p._M_cmpts.size(); + else + capacity += 1; + + __try + { + _M_cmpts.type(_Type::_Multi); + _M_cmpts.reserve(capacity); + _Cmpt* output = _M_cmpts._M_impl->end(); + + if (orig_type != _Type::_Multi) + { + // Create single component from original path + auto ptr = ::new(output++) _Cmpt({}, orig_type, 0); + ++_M_cmpts._M_impl->_M_size; + ptr->_M_pathname.reserve(_M_pathname.length() + extra.length()); + ptr->_M_pathname = _M_pathname; + ptr->_M_pathname += extra; + +#if SLASHSLASH_IS_ROOTNAME + if (orig_type == _Type::_Root_name) + { + basic_string_view s(p._M_pathname); + ::new(output++) _Cmpt(s.substr(extra.length(), 1), + _Type::_Root_dir, orig_pathlen + extra.length()); + ++_M_cmpts._M_impl->_M_size; + } +#endif + } + else if (orig_filenamelen == 0 && it != last) + { + // Remove empty filename at end of original path. + _M_cmpts.pop_back(); + --output; + } + + if (it != last && it->_M_type() == _Type::_Root_name) + { + basic_string_view s = it->_M_pathname; + auto pos = orig_pathlen; +#if SLASHSLASH_IS_ROOTNAME + s.remove_prefix(2); + pos += 2; +#endif + ::new(output++) _Cmpt(s, _Type::_Filename, pos); + ++_M_cmpts._M_impl->_M_size; + ++it; + } + + if (it != last && it->_M_type() == _Type::_Root_dir) + { + ++it; + if (it == last) + { + // This root-dir becomes a trailing slash + auto pos = _M_pathname.length() + p._M_pathname.length(); + ::new(output++) _Cmpt({}, _Type::_Filename, pos); + ++_M_cmpts._M_impl->_M_size; + } + } + + while (it != last) + { + auto pos = it->_M_pos + orig_pathlen; + ::new(output++) _Cmpt(it->_M_pathname, _Type::_Filename, pos); + ++_M_cmpts._M_impl->_M_size; + ++it; + } + + _M_pathname += p._M_pathname; + + if (is_dir_sep(_M_pathname.back())) + { + ::new(output++) _Cmpt({}, _Type::_Filename, _M_pathname.length()); + ++_M_cmpts._M_impl->_M_size; + } + } + __catch (...) + { + _M_pathname.resize(orig_pathlen); + if (orig_type == _Type::_Multi) + { + if (_M_cmpts.size() > orig_size) + _M_cmpts._M_erase_from(_M_cmpts.begin() + orig_size); + if (orig_filenamelen != -1) + { + if (_M_cmpts.size() == orig_size) + { + auto& back = _M_cmpts.back(); + back._M_pathname.resize(orig_filenamelen); + if (orig_filenamelen == 0) + back._M_pos = orig_pathlen; + } + else + { + auto output = _M_cmpts._M_impl->end(); + ::new(output) _Cmpt({}, _Type::_Filename, orig_pathlen); + ++_M_cmpts._M_impl->_M_size; + } + } + } + else + _M_cmpts.clear(); + _M_cmpts.type(orig_type); + __throw_exception_again; + } + return *this; +} + +// [fs.path.concat] +void +path::_M_concat(basic_string_view s) +{ + if (s.empty()) + return; + + if (this->empty()) + { + operator=(s); + return; + } + + const auto orig_pathlen = _M_pathname.length(); + const auto orig_type = _M_type(); + const auto orig_size = _M_cmpts.size(); + int orig_filenamelen = -1; + basic_string_view extra; + + // Copy the input into _M_pathname: + _M_pathname += s; + // Update s to refer to the new copy (this ensures s is not a dangling + // reference to deallocated characters, in the case where it was referring + // into _M_pathname or a member of _M_cmpts). + s = _M_pathname; + const auto orig_pathname = s.substr(0, orig_pathlen); + s.remove_prefix(orig_pathlen); + + _Parser parser(s, orig_pathlen); + auto cmpt = parser.next(); + + if (cmpt.str.data() == s.data()) + { + // See if there's a filename or root-name at the end of the original path + // that we can add to. + if (_M_type() == _Type::_Filename +#if SLASHSLASH_IS_ROOTNAME + || _M_type() == _Type::_Root_name +#endif + ) + { + if (cmpt.str.length() == s.length()) + { + // Simplest case where we just need to add the whole of s + // to the original path, which was already done above. + return; + } + // Only the first component of s should be appended, do so below: + extra = cmpt.str; + cmpt = {}; // so we don't process it again + } + else if (_M_type() == _Type::_Multi + && _M_cmpts.back()._M_type() == _Type::_Filename) + { + auto& back = _M_cmpts.back(); + if (cmpt.str.length() == s.length()) + { + back._M_pathname += s; + return; + } + + orig_filenamelen = back._M_pathname.length(); + back._M_pathname += cmpt.str; + extra = cmpt.str; + cmpt = {}; + } + } + else if (is_dir_sep(orig_pathname.back()) && _M_type() == _Type::_Multi + && _M_cmpts.back()._M_type() == _Type::_Filename) + orig_filenamelen = 0; // original path had empty filename at end + + std::array<_Parser::cmpt, 64> buf; + auto next = buf.begin(); + + if (cmpt.valid()) + *next++ = cmpt; + + cmpt = parser.next(); + while (cmpt.valid() && next != buf.end()) + { + *next++ = cmpt; + cmpt = parser.next(); + } + + int capacity = 0; + if (_M_type() == _Type::_Multi) + capacity += _M_cmpts.size(); + else + capacity += 1; + + capacity += next - buf.begin(); + + if (cmpt.valid()) // filled buffer before parsing whole input + { + ++capacity; + _Parser parser2(parser); + while (parser2.next().valid()) + ++capacity; + } + +#if SLASHSLASH_IS_ROOTNAME + if (orig_type == _Type::_Root_name) + ++capacity; // Need to insert root-directory after root-name +#endif + + __try + { + _M_cmpts.type(_Type::_Multi); + _M_cmpts.reserve(capacity); + _Cmpt* output = _M_cmpts._M_impl->end(); + auto it = buf.begin(); + + if (orig_type != _Type::_Multi) + { + // Create single component from original path + auto p = ::new(output++) _Cmpt({}, orig_type, 0); + ++_M_cmpts._M_impl->_M_size; + p->_M_pathname.reserve(orig_pathname.length() + extra.length()); + p->_M_pathname = orig_pathname; + p->_M_pathname += extra; + +#if SLASHSLASH_IS_ROOTNAME + if (orig_type == _Type::_Root_name) + { + ::new(output++) _Cmpt(s.substr(extra.length(), 1), + _Type::_Root_dir, orig_pathlen + extra.length()); + ++_M_cmpts._M_impl->_M_size; + } +#endif + } + else if (orig_filenamelen == 0 && extra.empty()) + { + // Replace empty filename at end of original path. + std::prev(output)->_M_pathname = it->str; + std::prev(output)->_M_pos = parser.offset(*it); + ++it; + } + + while (it != next) + { + ::new(output++) _Cmpt(it->str, _Type::_Filename, parser.offset(*it)); + ++_M_cmpts._M_impl->_M_size; + ++it; + } + + if (next == buf.end()) + { + while (cmpt.valid()) + { + auto pos = parser.offset(cmpt); + ::new(output++) _Cmpt(cmpt.str, _Type::_Filename, pos); + ++_M_cmpts._M_impl->_M_size; + cmpt = parser.next(); + } + } + } + __catch (...) + { + _M_pathname.resize(orig_pathlen); + if (orig_type == _Type::_Multi) + { + _M_cmpts._M_erase_from(_M_cmpts.begin() + orig_size); + if (orig_filenamelen != -1) + { + auto& back = _M_cmpts.back(); + back._M_pathname.resize(orig_filenamelen); + if (orig_filenamelen == 0) + back._M_pos = orig_pathlen; + } + } + else + _M_cmpts.clear(); + _M_cmpts.type(orig_type); + __throw_exception_again; + } +} + +path& +path::remove_filename() +{ + if (_M_type() == _Type::_Multi) + { + if (!_M_cmpts.empty()) + { + auto cmpt = std::prev(_M_cmpts.end()); + if (cmpt->_M_type() == _Type::_Filename && !cmpt->empty()) + { + _M_pathname.erase(cmpt->_M_pos); + auto prev = std::prev(cmpt); + if (prev->_M_type() == _Type::_Root_dir + || prev->_M_type() == _Type::_Root_name) + { + _M_cmpts.pop_back(); + if (_M_cmpts.size() == 1) + { + _M_cmpts.type(_M_cmpts.front()._M_type()); + _M_cmpts.clear(); + } + } + else + cmpt->clear(); + } + } + } + else if (_M_type() == _Type::_Filename) + clear(); + return *this; +} + +path& +path::replace_filename(const path& replacement) +{ + remove_filename(); + operator/=(replacement); + return *this; +} + +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS +const fs::path::value_type dot = L'.'; +#else +const fs::path::value_type dot = '.'; +#endif + +path& +path::replace_extension(const path& replacement) +{ + auto ext = _M_find_extension(); + // Any existing extension() is removed + if (ext.first && ext.second != string_type::npos) + { + if (ext.first == &_M_pathname) + _M_pathname.erase(ext.second); + else + { + const auto& back = _M_cmpts.back(); + if (ext.first != &back._M_pathname) + _GLIBCXX_THROW_OR_ABORT( + std::logic_error("path::replace_extension failed")); + _M_pathname.erase(back._M_pos + ext.second); + } + } + // If replacement is not empty and does not begin with a dot character, + // a dot character is appended + if (!replacement.empty() && replacement.native()[0] != dot) + _M_pathname += dot; + operator+=(replacement); + return *this; +} + +int +path::compare(const path& p) const noexcept +{ + if (_M_pathname == p._M_pathname) + return 0; + + basic_string_view lroot, rroot; + if (_M_type() == _Type::_Root_name) + lroot = _M_pathname; + else if (_M_type() == _Type::_Multi + && _M_cmpts.front()._M_type() == _Type::_Root_name) + lroot = _M_cmpts.front()._M_pathname; + if (p._M_type() == _Type::_Root_name) + rroot = p._M_pathname; + else if (p._M_type() == _Type::_Multi + && p._M_cmpts.front()._M_type() == _Type::_Root_name) + rroot = p._M_cmpts.front()._M_pathname; + if (int rootNameComparison = lroot.compare(rroot)) + return rootNameComparison; + + if (!this->has_root_directory() && p.has_root_directory()) + return -1; + else if (this->has_root_directory() && !p.has_root_directory()) + return +1; + + using Iterator = const _Cmpt*; + Iterator begin1, end1, begin2, end2; + if (_M_type() == _Type::_Multi) + { + begin1 = _M_cmpts.begin(); + end1 = _M_cmpts.end(); + // Find start of this->relative_path() + while (begin1 != end1 && begin1->_M_type() != _Type::_Filename) + ++begin1; + } + else + begin1 = end1 = nullptr; + + if (p._M_type() == _Type::_Multi) + { + begin2 = p._M_cmpts.begin(); + end2 = p._M_cmpts.end(); + // Find start of p.relative_path() + while (begin2 != end2 && begin2->_M_type() != _Type::_Filename) + ++begin2; + } + else + begin2 = end2 = nullptr; + + if (_M_type() == _Type::_Filename) + { + if (p._M_type() == _Type::_Filename) + return native().compare(p.native()); + else if (begin2 != end2) + { + if (int ret = native().compare(begin2->native())) + return ret; + else + return ++begin2 == end2 ? 0 : -1; + } + else + return +1; + } + else if (p._M_type() == _Type::_Filename) + { + if (begin1 != end1) + { + if (int ret = begin1->native().compare(p.native())) + return ret; + else + return ++begin1 == end1 ? 0 : +1; + } + else + return -1; + } + + int count = 1; + while (begin1 != end1 && begin2 != end2) + { + if (int i = begin1->native().compare(begin2->native())) + return i; + ++begin1; + ++begin2; + ++count; + } + if (begin1 == end1) + { + if (begin2 == end2) + return 0; + return -count; + } + return count; +} + +int +path::compare(basic_string_view s) const noexcept +{ + if (_M_pathname == s) + return 0; + + _Parser parser(s); + + basic_string_view lroot, rroot; + if (_M_type() == _Type::_Root_name) + lroot = _M_pathname; + else if (_M_type() == _Type::_Multi + && _M_cmpts.front()._M_type() == _Type::_Root_name) + lroot = _M_cmpts.front()._M_pathname; + auto root_path = parser.root_path(); + if (root_path.first.type == _Type::_Root_name) + rroot = root_path.first.str; + if (int rootNameComparison = lroot.compare(rroot)) + return rootNameComparison; + + const bool has_root_dir = root_path.first.type == _Type::_Root_dir + || root_path.second.type == _Type::_Root_dir; + if (!this->has_root_directory() && has_root_dir) + return -1; + else if (this->has_root_directory() && !has_root_dir) + return +1; + + using Iterator = const _Cmpt*; + Iterator begin1, end1; + if (_M_type() == _Type::_Filename) + { + auto cmpt = parser.next(); + if (cmpt.valid()) + { + if (int ret = this->native().compare(cmpt.str)) + return ret; + return parser.next().valid() ? -1 : 0; + } + else + return +1; + } + else if (_M_type() == _Type::_Multi) + { + begin1 = _M_cmpts.begin(); + end1 = _M_cmpts.end(); + while (begin1 != end1 && begin1->_M_type() != _Type::_Filename) + ++begin1; + } + else + begin1 = end1 = nullptr; + + int count = 1; + auto cmpt = parser.next(); + while (begin1 != end1 && cmpt.valid()) + { + if (int i = begin1->native().compare(cmpt.str)) + return i; + ++begin1; + cmpt = parser.next(); + ++count; + } + if (begin1 == end1) + { + if (!cmpt.valid()) + return 0; + return -count; + } + return +count; +} + +path +path::root_name() const +{ + path __ret; + if (_M_type() == _Type::_Root_name) + __ret = *this; + else if (_M_cmpts.size() && _M_cmpts.begin()->_M_type() == _Type::_Root_name) + __ret = *_M_cmpts.begin(); + return __ret; +} + +path +path::root_directory() const +{ + path __ret; + if (_M_type() == _Type::_Root_dir) + { + __ret._M_cmpts.type(_Type::_Root_dir); + __ret._M_pathname.assign(1, preferred_separator); + } + else if (!_M_cmpts.empty()) + { + auto __it = _M_cmpts.begin(); + if (__it->_M_type() == _Type::_Root_name) + ++__it; + if (__it != _M_cmpts.end() && __it->_M_type() == _Type::_Root_dir) + __ret = *__it; + } + return __ret; +} + +path +path::root_path() const +{ + path __ret; + if (_M_type() == _Type::_Root_name) + __ret = *this; + else if (_M_type() == _Type::_Root_dir) + { + __ret._M_pathname.assign(1, preferred_separator); + __ret._M_cmpts.type(_Type::_Root_dir); + } + else if (!_M_cmpts.empty()) + { + auto __it = _M_cmpts.begin(); + if (__it->_M_type() == _Type::_Root_name) + { + __ret = *__it++; + if (__it != _M_cmpts.end() && __it->_M_type() == _Type::_Root_dir) + __ret /= *__it; + } + else if (__it->_M_type() == _Type::_Root_dir) + __ret = *__it; + } + return __ret; +} + +path +path::relative_path() const +{ + path __ret; + if (_M_type() == _Type::_Filename) + __ret = *this; + else if (!_M_cmpts.empty()) + { + auto __it = _M_cmpts.begin(); + if (__it->_M_type() == _Type::_Root_name) + ++__it; + if (__it != _M_cmpts.end() && __it->_M_type() == _Type::_Root_dir) + ++__it; + if (__it != _M_cmpts.end()) + __ret.assign(_M_pathname.substr(__it->_M_pos)); + } + return __ret; +} + +path +path::parent_path() const +{ + path __ret; + if (!has_relative_path()) + __ret = *this; + else if (_M_cmpts.size() >= 2) + { + for (auto __it = _M_cmpts.begin(), __end = std::prev(_M_cmpts.end()); + __it != __end; ++__it) + { + __ret /= *__it; + } + } + return __ret; +} + +bool +path::has_root_name() const +{ + if (_M_type() == _Type::_Root_name) + return true; + if (!_M_cmpts.empty() && _M_cmpts.begin()->_M_type() == _Type::_Root_name) + return true; + return false; +} + +bool +path::has_root_directory() const +{ + if (_M_type() == _Type::_Root_dir) + return true; + if (!_M_cmpts.empty()) + { + auto __it = _M_cmpts.begin(); + if (__it->_M_type() == _Type::_Root_name) + ++__it; + if (__it != _M_cmpts.end() && __it->_M_type() == _Type::_Root_dir) + return true; + } + return false; +} + +bool +path::has_root_path() const +{ + if (_M_type() == _Type::_Root_name || _M_type() == _Type::_Root_dir) + return true; + if (!_M_cmpts.empty()) + { + auto __type = _M_cmpts.front()._M_type(); + if (__type == _Type::_Root_name || __type == _Type::_Root_dir) + return true; + } + return false; +} + +bool +path::has_relative_path() const +{ + if (_M_type() == _Type::_Filename && !_M_pathname.empty()) + return true; + if (!_M_cmpts.empty()) + { + auto __it = _M_cmpts.begin(); + if (__it->_M_type() == _Type::_Root_name) + ++__it; + if (__it != _M_cmpts.end() && __it->_M_type() == _Type::_Root_dir) + ++__it; + if (__it != _M_cmpts.end() && !__it->_M_pathname.empty()) + return true; + } + return false; +} + + +bool +path::has_parent_path() const +{ + if (!has_relative_path()) + return !empty(); + return _M_cmpts.size() >= 2; +} + +bool +path::has_filename() const +{ + if (empty()) + return false; + if (_M_type() == _Type::_Filename) + return !_M_pathname.empty(); + if (_M_type() == _Type::_Multi) + { + if (_M_pathname.back() == preferred_separator) + return false; + return _M_cmpts.back().has_filename(); + } + return false; +} + +namespace +{ + inline bool is_dot(fs::path::value_type c) { return c == dot; } + + 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]); + } +} // namespace + +path +path::lexically_normal() const +{ + /* + C++17 [fs.path.generic] p6 + - If the path is empty, stop. + - Replace each slash character in the root-name with a preferred-separator. + - Replace each directory-separator with a preferred-separator. + - Remove each dot filename and any immediately following directory-separator. + - As long as any appear, remove a non-dot-dot filename immediately followed + by a directory-separator and a dot-dot filename, along with any immediately + following directory-separator. + - If there is a root-directory, remove all dot-dot filenames and any + directory-separators immediately following them. + - If the last filename is dot-dot, remove any trailing directory-separator. + - If the path is empty, add a dot. + */ + path ret; + // If the path is empty, stop. + if (empty()) + return ret; + for (auto& p : *this) + { +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + // Replace each slash character in the root-name + if (p._M_type() == _Type::_Root_name || p._M_type() == _Type::_Root_dir) + { + string_type s = p.native(); + std::replace(s.begin(), s.end(), L'/', L'\\'); + ret /= s; + continue; + } +#endif + if (is_dotdot(p)) + { + if (ret.has_filename()) + { + // remove a non-dot-dot filename immediately followed by /.. + if (!is_dotdot(ret.filename())) + ret.remove_filename(); + else + ret /= p; + } + else if (!ret.has_relative_path()) + { + // remove a dot-dot filename immediately after root-directory + if (!ret.has_root_directory()) + ret /= p; + } + else + { + // Got a path with a relative path (i.e. at least one non-root + // element) and no filename at the end (i.e. empty last element), + // so must have a trailing slash. See what is before it. + auto elem = ret._M_cmpts.end() - 2; + if (elem->has_filename() && !is_dotdot(*elem)) + { + // Remove the filename before the trailing slash + // (equiv. to ret = ret.parent_path().remove_filename()) + + if (elem == ret._M_cmpts.begin()) + ret.clear(); + else + { + ret._M_pathname.erase(elem->_M_pos); + // Remove empty filename at the end: + ret._M_cmpts.pop_back(); + // If we still have a trailing non-root dir separator + // then leave an empty filename at the end: + if (std::prev(elem)->_M_type() == _Type::_Filename) + elem->clear(); + else // remove the component completely: + ret._M_cmpts.pop_back(); + } + } + else + // Append the ".." to something ending in "../" which happens + // when normalising paths like ".././.." and "../a/../.." + ret /= p; + } + } + else if (is_dot(p)) + ret /= path(); +#if SLASHSLASH_IS_ROOTNAME + else if (p._M_type() == _Type::_Root_dir) + ret += '/'; // using operator/=('/') would replace whole of ret +#endif + else + ret /= p; + } + + if (ret._M_cmpts.size() >= 2) + { + auto back = std::prev(ret.end()); + // If the last filename is dot-dot, ... + if (back->empty() && is_dotdot(*std::prev(back))) + // ... remove any trailing directory-separator. + ret = ret.parent_path(); + } + // If the path is empty, add a dot. + else if (ret.empty()) + ret = "."; + + return ret; +} + +path +path::lexically_relative(const path& base) const +{ + path ret; + if (root_name() != base.root_name()) + return ret; + if (is_absolute() != base.is_absolute()) + return ret; + if (!has_root_directory() && base.has_root_directory()) + return ret; + auto [a, b] = std::mismatch(begin(), end(), base.begin(), base.end()); + if (a == end() && b == base.end()) + ret = "."; + else + { + int n = 0; + for (; b != base.end(); ++b) + { + const path& p = *b; + if (is_dotdot(p)) + --n; + else if (!p.empty() && !is_dot(p)) + ++n; + } + if (n == 0 && (a == end() || a->empty())) + ret = "."; + else if (n >= 0) + { + const path dotdot(".."); + while (n--) + ret /= dotdot; + for (; a != end(); ++a) + ret /= *a; + } + } + return ret; +} + +path +path::lexically_proximate(const path& base) const +{ + path rel = lexically_relative(base); + if (rel.empty()) + rel = *this; + return rel; +} + +std::pair +path::_M_find_extension() const +{ + const string_type* s = nullptr; + + if (_M_type() == _Type::_Filename) + s = &_M_pathname; + else if (_M_type() == _Type::_Multi && !_M_cmpts.empty()) + { + const auto& c = _M_cmpts.back(); + if (c._M_type() == _Type::_Filename) + s = &c._M_pathname; + } + + if (s) + { + if (auto sz = s->size()) + { + if (sz <= 2 && (*s)[0] == dot) + return { s, string_type::npos }; + const auto pos = s->rfind(dot); + return { s, pos ? pos : string_type::npos }; + } + } + return {}; +} + +void +path::_M_split_cmpts() +{ + _M_cmpts.clear(); + + if (_M_pathname.empty()) + { + _M_cmpts.type(_Type::_Filename); + return; + } + if (_M_pathname.length() == 1 && _M_pathname[0] == preferred_separator) + { + _M_cmpts.type(_Type::_Root_dir); + return; + } + + _Parser parser(_M_pathname); + + std::array<_Parser::cmpt, 64> buf; + auto next = buf.begin(); + + // look for root name or root directory + auto root_path = parser.root_path(); + if (root_path.first.valid()) + { + *next++ = root_path.first; + if (root_path.second.valid()) + *next++ = root_path.second; + } + + auto cmpt = parser.next(); + while (cmpt.valid()) + { + do + { + *next++ = cmpt; + cmpt = parser.next(); + } + while (cmpt.valid() && next != buf.end()); + + if (next == buf.end()) + { + _M_cmpts.type(_Type::_Multi); + _M_cmpts.reserve(_M_cmpts.size() + buf.size()); + auto output = _M_cmpts._M_impl->end(); + for (auto& c : buf) + { + auto pos = c.str.data() - _M_pathname.data(); + ::new(output++) _Cmpt(c.str, c.type, pos); + ++_M_cmpts._M_impl->_M_size; + } + next = buf.begin(); + } + } + + if (auto n = next - buf.begin()) + { + if (n == 1 && _M_cmpts.empty()) + { + _M_cmpts.type(buf.front().type); + return; + } + + _M_cmpts.type(_Type::_Multi); + _M_cmpts.reserve(_M_cmpts.size() + n, true); + auto output = _M_cmpts._M_impl->end(); + for (int i = 0; i < n; ++i) + { + auto c = buf[i]; + auto pos = c.str.data() - _M_pathname.data(); + ::new(output++) _Cmpt(c.str, c.type, pos); + ++_M_cmpts._M_impl->_M_size; + } + } +} + +path::string_type +path::_S_convert_loc(const char* __first, const char* __last, + const std::locale& __loc) +{ +#if _GLIBCXX_USE_WCHAR_T + auto& __cvt = std::use_facet>(__loc); + basic_string __ws; + if (!__str_codecvt_in(__first, __last, __ws, __cvt)) + _GLIBCXX_THROW_OR_ABORT(filesystem_error( + "Cannot convert character sequence", + std::make_error_code(errc::illegal_byte_sequence))); +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + return __ws; +#else + return _Cvt::_S_convert(__ws.data(), __ws.data() + __ws.size()); +#endif +#else + return {__first, __last}; +#endif +} + +std::size_t +fs::hash_value(const path& p) noexcept +{ + // [path.non-member] + // "If for two paths, p1 == p2 then hash_value(p1) == hash_value(p2)." + // Equality works as if by traversing the range [begin(), end()), meaning + // e.g. path("a//b") == path("a/b"), so we cannot simply hash _M_pathname + // but need to iterate over individual elements. Use the hash_combine from + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3876.pdf + size_t seed = 0; + for (const auto& x : p) + { + seed ^= std::hash()(x.native()) + 0x9e3779b9 + + (seed<<6) + (seed>>2); + } + return seed; +} + +struct fs::filesystem_error::_Impl +{ + _Impl(const string& what_arg, const path& p1, const path& p2) + : path1(p1), path2(p2), what(make_what(what_arg, &p1, &p2)) + { } + + _Impl(const string& what_arg, const path& p1) + : path1(p1), path2(), what(make_what(what_arg, &p1, nullptr)) + { } + + _Impl(const string& what_arg) + : what(make_what(what_arg, nullptr, nullptr)) + { } + + static std::string + make_what(const std::string& s, const path* p1, const path* p2) + { + const std::string pstr1 = p1 ? p1->u8string() : std::string{}; + const std::string pstr2 = p2 ? p2->u8string() : std::string{}; + const size_t len = 18 + s.length() + + (pstr1.length() ? pstr1.length() + 3 : 0) + + (pstr2.length() ? pstr2.length() + 3 : 0); + std::string w; + w.reserve(len); + w = "filesystem error: "; + w += s; + if (p1) + { + w += " ["; + w += pstr1; + w += ']'; + if (p2) + { + w += " ["; + w += pstr2; + w += ']'; + } + } + return w; + } + + path path1; + path path2; + std::string what; +}; + +template class std::__shared_ptr; + +fs::filesystem_error:: +filesystem_error(const string& what_arg, error_code ec) +: system_error(ec, what_arg), + _M_impl(std::__make_shared<_Impl>(what_arg)) +{ } + +fs::filesystem_error:: +filesystem_error(const string& what_arg, const path& p1, error_code ec) +: system_error(ec, what_arg), + _M_impl(std::__make_shared<_Impl>(what_arg, p1)) +{ } + +fs::filesystem_error:: +filesystem_error(const string& what_arg, const path& p1, const path& p2, + error_code ec) +: system_error(ec, what_arg), + _M_impl(std::__make_shared<_Impl>(what_arg, p1, p2)) +{ } + +fs::filesystem_error::~filesystem_error() = default; + +const fs::path& +fs::filesystem_error::path1() const noexcept +{ return _M_impl->path1; } + +const fs::path& +fs::filesystem_error::path2() const noexcept +{ return _M_impl->path2; } + +const char* +fs::filesystem_error::what() const noexcept +{ return _M_impl->what.c_str(); } diff --git a/libstdc++-v3/src/filesystem/Makefile.am b/libstdc++-v3/src/filesystem/Makefile.am index 12367c7c02c..6f2a9f63b8a 100644 --- a/libstdc++-v3/src/filesystem/Makefile.am +++ b/libstdc++-v3/src/filesystem/Makefile.am @@ -32,8 +32,7 @@ cxx11_abi_sources = \ cow-ops.cc \ cow-path.cc \ cow-std-dir.cc \ - cow-std-ops.cc \ - cow-std-path.cc + cow-std-ops.cc else cxx11_abi_sources = endif @@ -44,7 +43,6 @@ sources = \ path.cc \ std-dir.cc \ std-ops.cc \ - std-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 f2345118033..12524ff1cc6 100644 --- a/libstdc++-v3/src/filesystem/Makefile.in +++ b/libstdc++-v3/src/filesystem/Makefile.in @@ -151,9 +151,9 @@ LTLIBRARIES = $(toolexeclib_LTLIBRARIES) libstdc__fs_la_LIBADD = @ENABLE_DUAL_ABI_TRUE@am__objects_1 = cow-dir.lo cow-ops.lo \ @ENABLE_DUAL_ABI_TRUE@ cow-path.lo cow-std-dir.lo \ -@ENABLE_DUAL_ABI_TRUE@ cow-std-ops.lo cow-std-path.lo +@ENABLE_DUAL_ABI_TRUE@ cow-std-ops.lo am__objects_2 = dir.lo ops.lo path.lo std-dir.lo std-ops.lo \ - std-path.lo $(am__objects_1) + $(am__objects_1) am_libstdc__fs_la_OBJECTS = $(am__objects_2) libstdc__fs_la_OBJECTS = $(am_libstdc__fs_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -444,8 +444,7 @@ headers = @ENABLE_DUAL_ABI_TRUE@ cow-ops.cc \ @ENABLE_DUAL_ABI_TRUE@ cow-path.cc \ @ENABLE_DUAL_ABI_TRUE@ cow-std-dir.cc \ -@ENABLE_DUAL_ABI_TRUE@ cow-std-ops.cc \ -@ENABLE_DUAL_ABI_TRUE@ cow-std-path.cc +@ENABLE_DUAL_ABI_TRUE@ cow-std-ops.cc sources = \ dir.cc \ @@ -453,7 +452,6 @@ sources = \ path.cc \ std-dir.cc \ std-ops.cc \ - std-path.cc \ ${cxx11_abi_sources} diff --git a/libstdc++-v3/src/filesystem/cow-std-path.cc b/libstdc++-v3/src/filesystem/cow-std-path.cc deleted file mode 100644 index f0717aef876..00000000000 --- a/libstdc++-v3/src/filesystem/cow-std-path.cc +++ /dev/null @@ -1,26 +0,0 @@ -// Class filesystem::path -*- C++ -*- - -// Copyright (C) 2015-2019 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 -// . - -#define _GLIBCXX_USE_CXX11_ABI 0 -#include "std-path.cc" diff --git a/libstdc++-v3/src/filesystem/std-path.cc b/libstdc++-v3/src/filesystem/std-path.cc deleted file mode 100644 index 34de52f3a0f..00000000000 --- a/libstdc++-v3/src/filesystem/std-path.cc +++ /dev/null @@ -1,2007 +0,0 @@ -// Class filesystem::path -*- C++ -*- - -// Copyright (C) 2014-2019 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 -// . - -#ifndef _GLIBCXX_USE_CXX11_ABI -# define _GLIBCXX_USE_CXX11_ABI 1 -#endif - -#ifdef __CYGWIN__ -// Interpret "//x" as a root-name, not root-dir + filename -# define SLASHSLASH_IS_ROOTNAME 1 -#endif - -#include -#include -#include - -namespace fs = std::filesystem; -using fs::path; - -static inline bool is_dir_sep(path::value_type ch) -{ -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - return ch == L'/' || ch == path::preferred_separator; -#else - return ch == '/'; -#endif -} - -struct path::_Parser -{ - using string_view_type = std::basic_string_view; - - struct cmpt - { - string_view_type str; - _Type type = _Type::_Multi; - - bool valid() const { return type != _Type::_Multi; } - }; - - string_view_type input; - string_view_type::size_type pos = 0; - size_t origin; - _Type last_type = _Type::_Multi; - - _Parser(string_view_type s, size_t o = 0) : input(s), origin(o) { } - - pair root_path() noexcept - { - pos = 0; - pair root; - - const size_t len = input.size(); - - // look for root name or root directory - if (is_dir_sep(input[0])) - { -#if SLASHSLASH_IS_ROOTNAME - // look for root name, such as "//foo" - if (len > 2 && input[1] == input[0]) - { - if (!is_dir_sep(input[2])) - { - // got root name, find its end - pos = 3; - while (pos < len && !is_dir_sep(input[pos])) - ++pos; - root.first.str = input.substr(0, pos); - root.first.type = _Type::_Root_name; - - if (pos < len) // also got root directory - { - root.second.str = input.substr(pos, 1); - root.second.type = _Type::_Root_dir; - ++pos; - } - } - else - { - // got something like "///foo" which is just a root directory - // composed of multiple redundant directory separators - root.first.str = input.substr(0, 1); - root.first.type = _Type::_Root_dir; - pos += 2; - } - } - else -#endif - { - root.first.str = input.substr(0, 1); - root.first.type = _Type::_Root_dir; - ++pos; - } - // Find the start of the first filename - while (pos < len && is_dir_sep(input[pos])) - ++pos; - } -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - else if (len > 1 && input[1] == L':') - { - // got disk designator - root.first.str = input.substr(0, 2); - root.first.type = _Type::_Root_name; - if (len > 2 && is_dir_sep(input[2])) - { - root.second.str = input.substr(2, 1); - root.second.type = _Type::_Root_dir; - } - pos = input.find_first_not_of(L"/\\", 2); - } -#endif - - if (root.second.valid()) - last_type = root.second.type; - else - last_type = root.first.type; - - return root; - } - - cmpt next() noexcept - { -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - string_view_type sep = L"/\\"; -#else - char sep = '/'; -#endif - - const int last_pos = pos; - - cmpt f; - if (pos != input.npos) - { - pos = input.find_first_not_of(sep, pos); - if (pos != input.npos) - { - const auto end = input.find_first_of(sep, pos); - f.str = input.substr(pos, end - pos); - f.type = _Type::_Filename; - pos = end; - } - else if (last_type == _Type::_Filename - || (last_pos == 0 && !input.empty())) - { - // [fs.path.itr]/4 An empty element, if trailing non-root - // directory-separator present. - __glibcxx_assert(is_dir_sep(input.back())); - f.str = input.substr(input.length(), 0); - f.type = _Type::_Filename; - } - } - last_type = f.type; - return f; - } - - string_view_type::size_type - offset(const cmpt& c) const noexcept - { return origin + c.str.data() - input.data(); } -}; - -struct path::_List::_Impl -{ - using value_type = _Cmpt; - - _Impl(int cap) : _M_size(0), _M_capacity(cap) { } - - alignas(value_type) int _M_size; - int _M_capacity; - - using iterator = value_type*; - using const_iterator = const value_type*; - - iterator begin() { return reinterpret_cast(this + 1); } - iterator end() { return begin() + size(); } - - const_iterator begin() const - { return reinterpret_cast(this + 1); } - const_iterator end() const { return begin() + size(); } - - const value_type& front() const { return *begin(); } - const value_type& back() const { return end()[-1]; } - - int size() const { return _M_size; } - int capacity() const { return _M_capacity; } - bool empty() const { return _M_size == 0; } - - void clear() { std::destroy_n(begin(), _M_size); _M_size = 0; } - - void pop_back() - { - back().~_Cmpt(); - --_M_size; - } - - void _M_erase_from(const_iterator pos) - { - iterator first = begin() + (pos - begin()); - iterator last = end(); - std::destroy(first, last); - _M_size -= last - first; - } - - unique_ptr<_Impl, _Impl_deleter> copy() const - { - const auto n = size(); - void* p = ::operator new(sizeof(_Impl) + n * sizeof(value_type)); - unique_ptr<_Impl, _Impl_deleter> newptr(::new (p) _Impl{n}); - std::uninitialized_copy_n(begin(), n, newptr->begin()); - newptr->_M_size = n; - return newptr; - } - - // Clear the lowest two bits from the pointer (i.e. remove the _Type value) - static _Impl* notype(_Impl* p) - { - constexpr uintptr_t mask = ~(uintptr_t)0x3; - return reinterpret_cast<_Impl*>(reinterpret_cast(p) & mask); - } -}; - -void path::_List::_Impl_deleter::operator()(_Impl* p) const noexcept -{ - p = _Impl::notype(p); - if (p) - { - __glibcxx_assert(p->_M_size <= p->_M_capacity); - p->clear(); - ::operator delete(p, sizeof(*p) + p->_M_capacity * sizeof(value_type)); - } -} - -path::_List::_List() : _M_impl(reinterpret_cast<_Impl*>(_Type::_Filename)) { } - -path::_List::_List(const _List& other) -{ - if (!other.empty()) - _M_impl = other._M_impl->copy(); - else - type(other.type()); -} - -path::_List& -path::_List::operator=(const _List& other) -{ - if (!other.empty()) - { - // copy in-place if there is capacity - const int newsize = other._M_impl->size(); - auto impl = _Impl::notype(_M_impl.get()); - if (impl && impl->capacity() >= newsize) - { - const int oldsize = impl->_M_size; - auto to = impl->begin(); - auto from = other._M_impl->begin(); - const int minsize = std::min(newsize, oldsize); - for (int i = 0; i < minsize; ++i) - to[i]._M_pathname.reserve(from[i]._M_pathname.length()); - if (newsize > oldsize) - { - std::uninitialized_copy_n(to + oldsize, newsize - oldsize, - from + oldsize); - impl->_M_size = newsize; - } - else if (newsize < oldsize) - impl->_M_erase_from(impl->begin() + newsize); - std::copy_n(from, minsize, to); - type(_Type::_Multi); - } - else - _M_impl = other._M_impl->copy(); - } - else - { - clear(); - type(other.type()); - } - return *this; -} - -inline void -path::_List::type(_Type t) noexcept -{ - auto val = reinterpret_cast(_Impl::notype(_M_impl.release())); - _M_impl.reset(reinterpret_cast<_Impl*>(val | (unsigned char)t)); -} - -inline int -path::_List::size() const noexcept -{ - if (auto* ptr = _Impl::notype(_M_impl.get())) - return ptr->size(); - return 0; -} - -inline int -path::_List::capacity() const noexcept -{ - if (auto* ptr = _Impl::notype(_M_impl.get())) - return ptr->capacity(); - return 0; -} - -inline bool -path::_List::empty() const noexcept -{ - return size() == 0; -} - -inline auto -path::_List::begin() noexcept --> iterator -{ - __glibcxx_assert(!empty()); - if (auto* ptr = _Impl::notype(_M_impl.get())) - return ptr->begin(); - return nullptr; -} - -inline auto -path::_List::end() noexcept --> iterator -{ - __glibcxx_assert(!empty()); - if (auto* ptr = _Impl::notype(_M_impl.get())) - return ptr->end(); - return nullptr; -} - -auto -path::_List::begin() const noexcept --> const_iterator -{ - __glibcxx_assert(!empty()); - if (auto* ptr = _Impl::notype(_M_impl.get())) - return ptr->begin(); - return nullptr; -} - -auto -path::_List::end() const noexcept --> const_iterator -{ - __glibcxx_assert(!empty()); - if (auto* ptr = _Impl::notype(_M_impl.get())) - return ptr->end(); - return nullptr; -} - -inline auto -path::_List::front() noexcept --> value_type& -{ - return *_M_impl->begin(); -} - -inline auto -path::_List::back() noexcept --> value_type& -{ - return _M_impl->begin()[_M_impl->size() - 1]; -} - -inline auto -path::_List::front() const noexcept --> const value_type& -{ - return *_M_impl->begin(); -} - -inline auto -path::_List::back() const noexcept --> const value_type& -{ - return _M_impl->begin()[_M_impl->size() - 1]; -} - -inline void -path::_List::pop_back() -{ - __glibcxx_assert(size() > 0); - _M_impl->pop_back(); -} - -inline void -path::_List::_M_erase_from(const_iterator pos) -{ - _M_impl->_M_erase_from(pos); -} - -inline void -path::_List::clear() -{ - if (auto ptr = _Impl::notype(_M_impl.get())) - ptr->clear(); -} - -void -path::_List::reserve(int newcap, bool exact = false) -{ - // __glibcxx_assert(type() == _Type::_Multi); - - _Impl* curptr = _Impl::notype(_M_impl.get()); - - int curcap = curptr ? curptr->capacity() : 0; - - if (curcap < newcap) - { - if (!exact && newcap < int(1.5 * curcap)) - newcap = 1.5 * curcap; - - void* p = ::operator new(sizeof(_Impl) + newcap * sizeof(value_type)); - std::unique_ptr<_Impl, _Impl_deleter> newptr(::new(p) _Impl{newcap}); - const int cursize = curptr ? curptr->size() : 0; - if (cursize) - { - std::uninitialized_move_n(curptr->begin(), cursize, newptr->begin()); - newptr->_M_size = cursize; - } - std::swap(newptr, _M_impl); - } -} - -path& -path::operator=(const path& p) -{ - _M_pathname.reserve(p._M_pathname.length()); - _M_cmpts = p._M_cmpts; // might throw - _M_pathname = p._M_pathname; // won't throw because we reserved enough space - return *this; -} - -path& -path::operator/=(const path& __p) -{ -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - if (__p.is_absolute() - || (__p.has_root_name() && __p.root_name() != root_name())) - return operator=(__p); - - basic_string_view __lhs = _M_pathname; - bool __add_sep = false; - - if (__p.has_root_directory()) - { - // Remove any root directory and relative path - if (_M_type() != _Type::_Root_name) - { - if (!_M_cmpts.empty() - && _M_cmpts.front()._M_type() == _Type::_Root_name) - __lhs = _M_cmpts.front()._M_pathname; - else - __lhs = {}; - } - } - else if (has_filename() || (!has_root_directory() && is_absolute())) - __add_sep = true; - - basic_string_view __rhs = __p._M_pathname; - // Omit any root-name from the generic format pathname: - if (__p._M_type() == _Type::_Root_name) - __rhs = {}; - else if (!__p._M_cmpts.empty() - && __p._M_cmpts.front()._M_type() == _Type::_Root_name) - __rhs.remove_prefix(__p._M_cmpts.front()._M_pathname.size()); - - const size_t __len = __lhs.size() + (int)__add_sep + __rhs.size(); - const int __maxcmpts = _M_cmpts.size() + __p._M_cmpts.size(); - if (_M_pathname.capacity() < __len || _M_cmpts.capacity() < __maxcmpts) - { - // Construct new path and swap (strong exception-safety guarantee). - string_type __tmp; - __tmp.reserve(__len); - __tmp = __lhs; - if (__add_sep) - __tmp += preferred_separator; - __tmp += __rhs; - path __newp = std::move(__tmp); - swap(__newp); - } - else - { - _M_pathname = __lhs; - if (__add_sep) - _M_pathname += preferred_separator; - _M_pathname += __rhs; - __try - { - _M_split_cmpts(); - } - __catch (...) - { - __try - { - // try to restore original state - _M_pathname.resize(__lhs.length()); - _M_split_cmpts(); - } - __catch (...) - { - // give up, basic exception safety guarantee only: - clear(); - __throw_exception_again; - } - } - } -#else - // POSIX version is simpler than the specification in the standard, - // as any path with root-name or root-dir is absolute. - - if (__p.is_absolute() || this->empty()) - { - return operator=(__p); - } - - using string_view_type = basic_string_view; - - string_view_type sep; - if (has_filename()) - sep = { &preferred_separator, 1 }; // need to add a separator -#if SLASHSLASH_IS_ROOTNAME - else if (_M_type() == _Type::_Root_name) // root-name with no root-dir - sep = { &preferred_separator, 1 }; // need to add a separator -#endif - else if (__p.empty()) - return *this; // nothing to do - - const auto orig_pathlen = _M_pathname.length(); - const auto orig_size = _M_cmpts.size(); - const auto orig_type = _M_type(); - - int capacity = 0; - if (_M_type() == _Type::_Multi) - capacity += _M_cmpts.size(); - else if (!empty()) - capacity += 1; - if (__p._M_type() == _Type::_Multi) - capacity += __p._M_cmpts.size(); - else if (!__p.empty() || !sep.empty()) - capacity += 1; -#if SLASHSLASH_IS_ROOTNAME - if (orig_type == _Type::_Root_name) - ++capacity; // Need to insert root-directory after root-name -#endif - - if (orig_type == _Type::_Multi) - { - const int curcap = _M_cmpts._M_impl->capacity(); - if (capacity > curcap) - capacity = std::max(capacity, (int) (curcap * 1.5)); - } - - _M_pathname.reserve(_M_pathname.length() + sep.length() - + __p._M_pathname.length()); - - __try - { - _M_pathname += sep; - const auto basepos = _M_pathname.length(); - _M_pathname += __p.native(); - - _M_cmpts.type(_Type::_Multi); - _M_cmpts.reserve(capacity); - _Cmpt* output = _M_cmpts._M_impl->end(); - - if (orig_type == _Type::_Multi) - { - // Remove empty final component - if (_M_cmpts._M_impl->back().empty()) - { - _M_cmpts.pop_back(); - --output; - } - } - else if (orig_pathlen != 0) - { - // Create single component from original path - string_view_type s(_M_pathname.data(), orig_pathlen); - ::new(output++) _Cmpt(s, orig_type, 0); - ++_M_cmpts._M_impl->_M_size; -#if SLASHSLASH_IS_ROOTNAME - if (orig_type == _Type::_Root_name) - { - ::new(output++) _Cmpt(sep, _Type::_Root_dir, - orig_pathlen + sep.length()); - ++_M_cmpts._M_impl->_M_size; - } -#endif - } - - if (__p._M_type() == _Type::_Multi) - { - for (auto& c : *__p._M_cmpts._M_impl) - { - ::new(output++) _Cmpt(c._M_pathname, _Type::_Filename, - c._M_pos + basepos); - ++_M_cmpts._M_impl->_M_size; - } - } - else if (!__p.empty() || !sep.empty()) - { - __glibcxx_assert(__p._M_type() == _Type::_Filename); - ::new(output) _Cmpt(__p._M_pathname, __p._M_type(), basepos); - ++_M_cmpts._M_impl->_M_size; - } - } - __catch (...) - { - _M_pathname.resize(orig_pathlen); - if (orig_type == _Type::_Multi) - _M_cmpts._M_erase_from(_M_cmpts.begin() + orig_size); - else - _M_cmpts.clear(); - _M_cmpts.type(orig_type); - __throw_exception_again; - } -#endif - return *this; -} - -// [fs.path.append] -void -path::_M_append(basic_string_view s) -{ - _Parser parser(s); - auto root_path = parser.root_path(); - -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - bool is_absolute = root_path.second.type == _Type::_Root_dir; - bool has_root_name = root_path.first.type == _Type::_Root_name; - if (is_absolute || (has_root_name && root_path.first.str != root_name())) - { - operator=(s); - return; - } - - basic_string_view lhs = _M_pathname; - bool add_sep = false; - - bool has_root_directory = root_path.first.type == _Type::_Root_dir - || root_path.second.type == _Type::_Root_dir; - - if (has_root_directory) - { - // Remove any root directory and relative path - if (_M_type() != _Type::_Root_name) - { - if (!_M_cmpts.empty() - && _M_cmpts.front()._M_type() == _Type::_Root_name) - lhs = _M_cmpts.front()._M_pathname; - else - lhs = {}; - } - } - else if (has_filename() || (!has_root_directory && is_absolute)) - add_sep = true; - - basic_string_view rhs = s; - // Omit any root-name from the generic format pathname: - if (has_root_name) - rhs.remove_prefix(root_path.first.str.length()); - - // Construct new path and swap (strong exception-safety guarantee). - string_type tmp; - tmp.reserve(lhs.size() + (int)add_sep + rhs.size()); - tmp = lhs; - if (add_sep) - tmp += preferred_separator; - tmp += rhs; - path newp = std::move(tmp); - swap(newp); -#else - - bool is_absolute = root_path.first.type == _Type::_Root_dir - || root_path.second.type == _Type::_Root_dir; - if (is_absolute || this->empty()) - { - operator=(s); - return; - } - - const auto orig_pathlen = _M_pathname.length(); - const auto orig_size = _M_cmpts.size(); - const auto orig_type = _M_type(); - - basic_string_view sep; - if (has_filename()) - sep = { &preferred_separator, 1 }; // need to add a separator -#if SLASHSLASH_IS_ROOTNAME - else if (_M_type() == _Type::_Root_name) // root-name with no root-dir - sep = { &preferred_separator, 1 }; // need to add a separator -#endif - else if (s.empty()) - return; // nothing to do - - // Copy the input into _M_pathname: - _M_pathname += s; - _M_pathname.insert(orig_pathlen, sep); - // Update s to refer to the new copy (this ensures s is not a dangling - // reference to deallocated characters, in the case where it was referring - // into _M_pathname or a member of _M_cmpts). - s = _M_pathname; - const auto orig_pathname = s.substr(0, orig_pathlen); - s.remove_prefix(orig_pathlen + sep.length()); - - parser.input = s; // reset parser to use updated string view - const auto basepos = orig_pathname.length() + sep.length(); - parser.origin = basepos; - - std::array<_Parser::cmpt, 64> buf; - auto next = buf.begin(); - - int capacity = 0; - if (_M_type() == _Type::_Multi) - capacity += _M_cmpts.size(); - else if (!empty()) - capacity += 1; - - auto cmpt = parser.next(); - if (cmpt.valid()) - { - do - { - *next++ = cmpt; - cmpt = parser.next(); - } - while (cmpt.valid() && next != buf.end()); - - capacity += next - buf.begin(); - if (cmpt.valid()) // filled buffer before parsing whole input - { - ++capacity; - _Parser parser2(parser); - while (parser2.next().valid()) - ++capacity; - } - } - else if (!sep.empty()) - ++capacity; - -#if SLASHSLASH_IS_ROOTNAME - if (orig_type == _Type::_Root_name) - ++capacity; // Need to insert root-directory after root-name -#endif - - __try - { - _M_cmpts.type(_Type::_Multi); - _M_cmpts.reserve(capacity); - _Cmpt* output = _M_cmpts._M_impl->end(); - - if (orig_type == _Type::_Multi) - { - // Remove empty final component - if (_M_cmpts._M_impl->back().empty()) - { - _M_cmpts.pop_back(); - --output; - } - } - else if (orig_pathlen != 0) - { - // Create single component from original path - ::new(output++) _Cmpt(orig_pathname, orig_type, 0); - ++_M_cmpts._M_impl->_M_size; - -#if SLASHSLASH_IS_ROOTNAME - if (!sep.empty() && orig_type == _Type::_Root_name) - { - ::new(output++) _Cmpt(sep, _Type::_Root_dir, - orig_pathlen + sep.length()); - ++_M_cmpts._M_impl->_M_size; - } -#endif - } - - if (next != buf.begin()) - { - for (auto it = buf.begin(); it != next; ++it) - { - auto c = *it; - ::new(output++) _Cmpt(c.str, c.type, parser.offset(c)); - ++_M_cmpts._M_impl->_M_size; - } - while (cmpt.valid()) - { - ::new(output++) _Cmpt(cmpt.str, cmpt.type, parser.offset(cmpt)); - ++_M_cmpts._M_impl->_M_size; - cmpt = parser.next(); - } - } - else if (!sep.empty()) - { - // Empty filename at the end: - ::new(output) _Cmpt({}, _Type::_Filename, basepos); - ++_M_cmpts._M_impl->_M_size; - } - } - __catch (...) - { - _M_pathname.resize(orig_pathlen); - if (orig_type == _Type::_Multi) - _M_cmpts._M_erase_from(_M_cmpts.begin() + orig_size); - else - _M_cmpts.clear(); - _M_cmpts.type(orig_type); - __throw_exception_again; - } -#endif -} - -// [fs.path.concat] -path& -path::operator+=(const path& p) -{ - if (p.empty()) - return *this; - - if (this->empty()) - { - operator=(p); - return *this; - } - - const auto orig_pathlen = _M_pathname.length(); - const auto orig_type = _M_type(); - const auto orig_size = _M_cmpts.size(); - int orig_filenamelen = -1; - basic_string_view extra; - - // Ensure that '_M_pathname += p._M_pathname' won't throw: - _M_pathname.reserve(orig_pathlen + p._M_pathname.length()); - - _Cmpt c; - _Cmpt* it = nullptr; - _Cmpt* last = nullptr; - if (p._M_type() == _Type::_Multi) - { - it = p._M_cmpts._M_impl->begin(); - last = p._M_cmpts._M_impl->end(); - } - else - { - c = _Cmpt(p._M_pathname, p._M_type(), 0); - it = &c; - last = it + 1; - } - - if (it->_M_type() == _Type::_Filename) - { - // See if there's a filename or root-name at the end of the original path - // that we can add to. - if (_M_type() == _Type::_Filename -#if SLASHSLASH_IS_ROOTNAME - || _M_type() == _Type::_Root_name -#endif - ) - { - if (p._M_type() == _Type::_Filename) - { - // Simplest case where we just add the whole of p to the - // original path. - _M_pathname += p._M_pathname; - return *this; - } - // Only the first component of s should be appended, do so below: - extra = it->_M_pathname; - ++it; - } - else if (_M_type() == _Type::_Multi - && _M_cmpts.back()._M_type() == _Type::_Filename) - { - auto& back = _M_cmpts.back(); - if (p._M_type() == _Type::_Filename) - { - basic_string_view s = p._M_pathname; - back._M_pathname += s; - _M_pathname += s; - return *this; - } - - orig_filenamelen = back._M_pathname.length(); - back._M_pathname += it->_M_pathname; - extra = it->_M_pathname; - ++it; - } - } - else if (is_dir_sep(_M_pathname.back()) && _M_type() == _Type::_Multi - && _M_cmpts.back()._M_type() == _Type::_Filename) - orig_filenamelen = 0; // current path has empty filename at end - - int capacity = 0; - if (_M_type() == _Type::_Multi) - capacity += _M_cmpts.size(); - else - capacity += 1; - if (p._M_type() == _Type::_Multi) - capacity += p._M_cmpts.size(); - else - capacity += 1; - - __try - { - _M_cmpts.type(_Type::_Multi); - _M_cmpts.reserve(capacity); - _Cmpt* output = _M_cmpts._M_impl->end(); - - if (orig_type != _Type::_Multi) - { - // Create single component from original path - auto ptr = ::new(output++) _Cmpt({}, orig_type, 0); - ++_M_cmpts._M_impl->_M_size; - ptr->_M_pathname.reserve(_M_pathname.length() + extra.length()); - ptr->_M_pathname = _M_pathname; - ptr->_M_pathname += extra; - -#if SLASHSLASH_IS_ROOTNAME - if (orig_type == _Type::_Root_name) - { - basic_string_view s(p._M_pathname); - ::new(output++) _Cmpt(s.substr(extra.length(), 1), - _Type::_Root_dir, orig_pathlen + extra.length()); - ++_M_cmpts._M_impl->_M_size; - } -#endif - } - else if (orig_filenamelen == 0 && it != last) - { - // Remove empty filename at end of original path. - _M_cmpts.pop_back(); - --output; - } - - if (it != last && it->_M_type() == _Type::_Root_name) - { - basic_string_view s = it->_M_pathname; - auto pos = orig_pathlen; -#if SLASHSLASH_IS_ROOTNAME - s.remove_prefix(2); - pos += 2; -#endif - ::new(output++) _Cmpt(s, _Type::_Filename, pos); - ++_M_cmpts._M_impl->_M_size; - ++it; - } - - if (it != last && it->_M_type() == _Type::_Root_dir) - { - ++it; - if (it == last) - { - // This root-dir becomes a trailing slash - auto pos = _M_pathname.length() + p._M_pathname.length(); - ::new(output++) _Cmpt({}, _Type::_Filename, pos); - ++_M_cmpts._M_impl->_M_size; - } - } - - while (it != last) - { - auto pos = it->_M_pos + orig_pathlen; - ::new(output++) _Cmpt(it->_M_pathname, _Type::_Filename, pos); - ++_M_cmpts._M_impl->_M_size; - ++it; - } - - _M_pathname += p._M_pathname; - - if (is_dir_sep(_M_pathname.back())) - { - ::new(output++) _Cmpt({}, _Type::_Filename, _M_pathname.length()); - ++_M_cmpts._M_impl->_M_size; - } - } - __catch (...) - { - _M_pathname.resize(orig_pathlen); - if (orig_type == _Type::_Multi) - { - if (_M_cmpts.size() > orig_size) - _M_cmpts._M_erase_from(_M_cmpts.begin() + orig_size); - if (orig_filenamelen != -1) - { - if (_M_cmpts.size() == orig_size) - { - auto& back = _M_cmpts.back(); - back._M_pathname.resize(orig_filenamelen); - if (orig_filenamelen == 0) - back._M_pos = orig_pathlen; - } - else - { - auto output = _M_cmpts._M_impl->end(); - ::new(output) _Cmpt({}, _Type::_Filename, orig_pathlen); - ++_M_cmpts._M_impl->_M_size; - } - } - } - else - _M_cmpts.clear(); - _M_cmpts.type(orig_type); - __throw_exception_again; - } - return *this; -} - -// [fs.path.concat] -void -path::_M_concat(basic_string_view s) -{ - if (s.empty()) - return; - - if (this->empty()) - { - operator=(s); - return; - } - - const auto orig_pathlen = _M_pathname.length(); - const auto orig_type = _M_type(); - const auto orig_size = _M_cmpts.size(); - int orig_filenamelen = -1; - basic_string_view extra; - - // Copy the input into _M_pathname: - _M_pathname += s; - // Update s to refer to the new copy (this ensures s is not a dangling - // reference to deallocated characters, in the case where it was referring - // into _M_pathname or a member of _M_cmpts). - s = _M_pathname; - const auto orig_pathname = s.substr(0, orig_pathlen); - s.remove_prefix(orig_pathlen); - - _Parser parser(s, orig_pathlen); - auto cmpt = parser.next(); - - if (cmpt.str.data() == s.data()) - { - // See if there's a filename or root-name at the end of the original path - // that we can add to. - if (_M_type() == _Type::_Filename -#if SLASHSLASH_IS_ROOTNAME - || _M_type() == _Type::_Root_name -#endif - ) - { - if (cmpt.str.length() == s.length()) - { - // Simplest case where we just need to add the whole of s - // to the original path, which was already done above. - return; - } - // Only the first component of s should be appended, do so below: - extra = cmpt.str; - cmpt = {}; // so we don't process it again - } - else if (_M_type() == _Type::_Multi - && _M_cmpts.back()._M_type() == _Type::_Filename) - { - auto& back = _M_cmpts.back(); - if (cmpt.str.length() == s.length()) - { - back._M_pathname += s; - return; - } - - orig_filenamelen = back._M_pathname.length(); - back._M_pathname += cmpt.str; - extra = cmpt.str; - cmpt = {}; - } - } - else if (is_dir_sep(orig_pathname.back()) && _M_type() == _Type::_Multi - && _M_cmpts.back()._M_type() == _Type::_Filename) - orig_filenamelen = 0; // original path had empty filename at end - - std::array<_Parser::cmpt, 64> buf; - auto next = buf.begin(); - - if (cmpt.valid()) - *next++ = cmpt; - - cmpt = parser.next(); - while (cmpt.valid() && next != buf.end()) - { - *next++ = cmpt; - cmpt = parser.next(); - } - - int capacity = 0; - if (_M_type() == _Type::_Multi) - capacity += _M_cmpts.size(); - else - capacity += 1; - - capacity += next - buf.begin(); - - if (cmpt.valid()) // filled buffer before parsing whole input - { - ++capacity; - _Parser parser2(parser); - while (parser2.next().valid()) - ++capacity; - } - -#if SLASHSLASH_IS_ROOTNAME - if (orig_type == _Type::_Root_name) - ++capacity; // Need to insert root-directory after root-name -#endif - - __try - { - _M_cmpts.type(_Type::_Multi); - _M_cmpts.reserve(capacity); - _Cmpt* output = _M_cmpts._M_impl->end(); - auto it = buf.begin(); - - if (orig_type != _Type::_Multi) - { - // Create single component from original path - auto p = ::new(output++) _Cmpt({}, orig_type, 0); - ++_M_cmpts._M_impl->_M_size; - p->_M_pathname.reserve(orig_pathname.length() + extra.length()); - p->_M_pathname = orig_pathname; - p->_M_pathname += extra; - -#if SLASHSLASH_IS_ROOTNAME - if (orig_type == _Type::_Root_name) - { - ::new(output++) _Cmpt(s.substr(extra.length(), 1), - _Type::_Root_dir, orig_pathlen + extra.length()); - ++_M_cmpts._M_impl->_M_size; - } -#endif - } - else if (orig_filenamelen == 0 && extra.empty()) - { - // Replace empty filename at end of original path. - std::prev(output)->_M_pathname = it->str; - std::prev(output)->_M_pos = parser.offset(*it); - ++it; - } - - while (it != next) - { - ::new(output++) _Cmpt(it->str, _Type::_Filename, parser.offset(*it)); - ++_M_cmpts._M_impl->_M_size; - ++it; - } - - if (next == buf.end()) - { - while (cmpt.valid()) - { - auto pos = parser.offset(cmpt); - ::new(output++) _Cmpt(cmpt.str, _Type::_Filename, pos); - ++_M_cmpts._M_impl->_M_size; - cmpt = parser.next(); - } - } - } - __catch (...) - { - _M_pathname.resize(orig_pathlen); - if (orig_type == _Type::_Multi) - { - _M_cmpts._M_erase_from(_M_cmpts.begin() + orig_size); - if (orig_filenamelen != -1) - { - auto& back = _M_cmpts.back(); - back._M_pathname.resize(orig_filenamelen); - if (orig_filenamelen == 0) - back._M_pos = orig_pathlen; - } - } - else - _M_cmpts.clear(); - _M_cmpts.type(orig_type); - __throw_exception_again; - } -} - -path& -path::remove_filename() -{ - if (_M_type() == _Type::_Multi) - { - if (!_M_cmpts.empty()) - { - auto cmpt = std::prev(_M_cmpts.end()); - if (cmpt->_M_type() == _Type::_Filename && !cmpt->empty()) - { - _M_pathname.erase(cmpt->_M_pos); - auto prev = std::prev(cmpt); - if (prev->_M_type() == _Type::_Root_dir - || prev->_M_type() == _Type::_Root_name) - { - _M_cmpts.pop_back(); - if (_M_cmpts.size() == 1) - { - _M_cmpts.type(_M_cmpts.front()._M_type()); - _M_cmpts.clear(); - } - } - else - cmpt->clear(); - } - } - } - else if (_M_type() == _Type::_Filename) - clear(); - return *this; -} - -path& -path::replace_filename(const path& replacement) -{ - remove_filename(); - operator/=(replacement); - return *this; -} - -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS -const fs::path::value_type dot = L'.'; -#else -const fs::path::value_type dot = '.'; -#endif - -path& -path::replace_extension(const path& replacement) -{ - auto ext = _M_find_extension(); - // Any existing extension() is removed - if (ext.first && ext.second != string_type::npos) - { - if (ext.first == &_M_pathname) - _M_pathname.erase(ext.second); - else - { - const auto& back = _M_cmpts.back(); - if (ext.first != &back._M_pathname) - _GLIBCXX_THROW_OR_ABORT( - std::logic_error("path::replace_extension failed")); - _M_pathname.erase(back._M_pos + ext.second); - } - } - // If replacement is not empty and does not begin with a dot character, - // a dot character is appended - if (!replacement.empty() && replacement.native()[0] != dot) - _M_pathname += dot; - operator+=(replacement); - return *this; -} - -int -path::compare(const path& p) const noexcept -{ - if (_M_pathname == p._M_pathname) - return 0; - - basic_string_view lroot, rroot; - if (_M_type() == _Type::_Root_name) - lroot = _M_pathname; - else if (_M_type() == _Type::_Multi - && _M_cmpts.front()._M_type() == _Type::_Root_name) - lroot = _M_cmpts.front()._M_pathname; - if (p._M_type() == _Type::_Root_name) - rroot = p._M_pathname; - else if (p._M_type() == _Type::_Multi - && p._M_cmpts.front()._M_type() == _Type::_Root_name) - rroot = p._M_cmpts.front()._M_pathname; - if (int rootNameComparison = lroot.compare(rroot)) - return rootNameComparison; - - if (!this->has_root_directory() && p.has_root_directory()) - return -1; - else if (this->has_root_directory() && !p.has_root_directory()) - return +1; - - using Iterator = const _Cmpt*; - Iterator begin1, end1, begin2, end2; - if (_M_type() == _Type::_Multi) - { - begin1 = _M_cmpts.begin(); - end1 = _M_cmpts.end(); - // Find start of this->relative_path() - while (begin1 != end1 && begin1->_M_type() != _Type::_Filename) - ++begin1; - } - else - begin1 = end1 = nullptr; - - if (p._M_type() == _Type::_Multi) - { - begin2 = p._M_cmpts.begin(); - end2 = p._M_cmpts.end(); - // Find start of p.relative_path() - while (begin2 != end2 && begin2->_M_type() != _Type::_Filename) - ++begin2; - } - else - begin2 = end2 = nullptr; - - if (_M_type() == _Type::_Filename) - { - if (p._M_type() == _Type::_Filename) - return native().compare(p.native()); - else if (begin2 != end2) - { - if (int ret = native().compare(begin2->native())) - return ret; - else - return ++begin2 == end2 ? 0 : -1; - } - else - return +1; - } - else if (p._M_type() == _Type::_Filename) - { - if (begin1 != end1) - { - if (int ret = begin1->native().compare(p.native())) - return ret; - else - return ++begin1 == end1 ? 0 : +1; - } - else - return -1; - } - - int count = 1; - while (begin1 != end1 && begin2 != end2) - { - if (int i = begin1->native().compare(begin2->native())) - return i; - ++begin1; - ++begin2; - ++count; - } - if (begin1 == end1) - { - if (begin2 == end2) - return 0; - return -count; - } - return count; -} - -int -path::compare(basic_string_view s) const noexcept -{ - if (_M_pathname == s) - return 0; - - _Parser parser(s); - - basic_string_view lroot, rroot; - if (_M_type() == _Type::_Root_name) - lroot = _M_pathname; - else if (_M_type() == _Type::_Multi - && _M_cmpts.front()._M_type() == _Type::_Root_name) - lroot = _M_cmpts.front()._M_pathname; - auto root_path = parser.root_path(); - if (root_path.first.type == _Type::_Root_name) - rroot = root_path.first.str; - if (int rootNameComparison = lroot.compare(rroot)) - return rootNameComparison; - - const bool has_root_dir = root_path.first.type == _Type::_Root_dir - || root_path.second.type == _Type::_Root_dir; - if (!this->has_root_directory() && has_root_dir) - return -1; - else if (this->has_root_directory() && !has_root_dir) - return +1; - - using Iterator = const _Cmpt*; - Iterator begin1, end1; - if (_M_type() == _Type::_Filename) - { - auto cmpt = parser.next(); - if (cmpt.valid()) - { - if (int ret = this->native().compare(cmpt.str)) - return ret; - return parser.next().valid() ? -1 : 0; - } - else - return +1; - } - else if (_M_type() == _Type::_Multi) - { - begin1 = _M_cmpts.begin(); - end1 = _M_cmpts.end(); - while (begin1 != end1 && begin1->_M_type() != _Type::_Filename) - ++begin1; - } - else - begin1 = end1 = nullptr; - - int count = 1; - auto cmpt = parser.next(); - while (begin1 != end1 && cmpt.valid()) - { - if (int i = begin1->native().compare(cmpt.str)) - return i; - ++begin1; - cmpt = parser.next(); - ++count; - } - if (begin1 == end1) - { - if (!cmpt.valid()) - return 0; - return -count; - } - return +count; -} - -path -path::root_name() const -{ - path __ret; - if (_M_type() == _Type::_Root_name) - __ret = *this; - else if (_M_cmpts.size() && _M_cmpts.begin()->_M_type() == _Type::_Root_name) - __ret = *_M_cmpts.begin(); - return __ret; -} - -path -path::root_directory() const -{ - path __ret; - if (_M_type() == _Type::_Root_dir) - { - __ret._M_cmpts.type(_Type::_Root_dir); - __ret._M_pathname.assign(1, preferred_separator); - } - else if (!_M_cmpts.empty()) - { - auto __it = _M_cmpts.begin(); - if (__it->_M_type() == _Type::_Root_name) - ++__it; - if (__it != _M_cmpts.end() && __it->_M_type() == _Type::_Root_dir) - __ret = *__it; - } - return __ret; -} - -path -path::root_path() const -{ - path __ret; - if (_M_type() == _Type::_Root_name) - __ret = *this; - else if (_M_type() == _Type::_Root_dir) - { - __ret._M_pathname.assign(1, preferred_separator); - __ret._M_cmpts.type(_Type::_Root_dir); - } - else if (!_M_cmpts.empty()) - { - auto __it = _M_cmpts.begin(); - if (__it->_M_type() == _Type::_Root_name) - { - __ret = *__it++; - if (__it != _M_cmpts.end() && __it->_M_type() == _Type::_Root_dir) - __ret /= *__it; - } - else if (__it->_M_type() == _Type::_Root_dir) - __ret = *__it; - } - return __ret; -} - -path -path::relative_path() const -{ - path __ret; - if (_M_type() == _Type::_Filename) - __ret = *this; - else if (!_M_cmpts.empty()) - { - auto __it = _M_cmpts.begin(); - if (__it->_M_type() == _Type::_Root_name) - ++__it; - if (__it != _M_cmpts.end() && __it->_M_type() == _Type::_Root_dir) - ++__it; - if (__it != _M_cmpts.end()) - __ret.assign(_M_pathname.substr(__it->_M_pos)); - } - return __ret; -} - -path -path::parent_path() const -{ - path __ret; - if (!has_relative_path()) - __ret = *this; - else if (_M_cmpts.size() >= 2) - { - for (auto __it = _M_cmpts.begin(), __end = std::prev(_M_cmpts.end()); - __it != __end; ++__it) - { - __ret /= *__it; - } - } - return __ret; -} - -bool -path::has_root_name() const -{ - if (_M_type() == _Type::_Root_name) - return true; - if (!_M_cmpts.empty() && _M_cmpts.begin()->_M_type() == _Type::_Root_name) - return true; - return false; -} - -bool -path::has_root_directory() const -{ - if (_M_type() == _Type::_Root_dir) - return true; - if (!_M_cmpts.empty()) - { - auto __it = _M_cmpts.begin(); - if (__it->_M_type() == _Type::_Root_name) - ++__it; - if (__it != _M_cmpts.end() && __it->_M_type() == _Type::_Root_dir) - return true; - } - return false; -} - -bool -path::has_root_path() const -{ - if (_M_type() == _Type::_Root_name || _M_type() == _Type::_Root_dir) - return true; - if (!_M_cmpts.empty()) - { - auto __type = _M_cmpts.front()._M_type(); - if (__type == _Type::_Root_name || __type == _Type::_Root_dir) - return true; - } - return false; -} - -bool -path::has_relative_path() const -{ - if (_M_type() == _Type::_Filename && !_M_pathname.empty()) - return true; - if (!_M_cmpts.empty()) - { - auto __it = _M_cmpts.begin(); - if (__it->_M_type() == _Type::_Root_name) - ++__it; - if (__it != _M_cmpts.end() && __it->_M_type() == _Type::_Root_dir) - ++__it; - if (__it != _M_cmpts.end() && !__it->_M_pathname.empty()) - return true; - } - return false; -} - - -bool -path::has_parent_path() const -{ - if (!has_relative_path()) - return !empty(); - return _M_cmpts.size() >= 2; -} - -bool -path::has_filename() const -{ - if (empty()) - return false; - if (_M_type() == _Type::_Filename) - return !_M_pathname.empty(); - if (_M_type() == _Type::_Multi) - { - if (_M_pathname.back() == preferred_separator) - return false; - return _M_cmpts.back().has_filename(); - } - return false; -} - -namespace -{ - inline bool is_dot(fs::path::value_type c) { return c == dot; } - - 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]); - } -} // namespace - -path -path::lexically_normal() const -{ - /* - C++17 [fs.path.generic] p6 - - If the path is empty, stop. - - Replace each slash character in the root-name with a preferred-separator. - - Replace each directory-separator with a preferred-separator. - - Remove each dot filename and any immediately following directory-separator. - - As long as any appear, remove a non-dot-dot filename immediately followed - by a directory-separator and a dot-dot filename, along with any immediately - following directory-separator. - - If there is a root-directory, remove all dot-dot filenames and any - directory-separators immediately following them. - - If the last filename is dot-dot, remove any trailing directory-separator. - - If the path is empty, add a dot. - */ - path ret; - // If the path is empty, stop. - if (empty()) - return ret; - for (auto& p : *this) - { -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - // Replace each slash character in the root-name - if (p._M_type() == _Type::_Root_name || p._M_type() == _Type::_Root_dir) - { - string_type s = p.native(); - std::replace(s.begin(), s.end(), L'/', L'\\'); - ret /= s; - continue; - } -#endif - if (is_dotdot(p)) - { - if (ret.has_filename()) - { - // remove a non-dot-dot filename immediately followed by /.. - if (!is_dotdot(ret.filename())) - ret.remove_filename(); - else - ret /= p; - } - else if (!ret.has_relative_path()) - { - // remove a dot-dot filename immediately after root-directory - if (!ret.has_root_directory()) - ret /= p; - } - else - { - // Got a path with a relative path (i.e. at least one non-root - // element) and no filename at the end (i.e. empty last element), - // so must have a trailing slash. See what is before it. - auto elem = ret._M_cmpts.end() - 2; - if (elem->has_filename() && !is_dotdot(*elem)) - { - // Remove the filename before the trailing slash - // (equiv. to ret = ret.parent_path().remove_filename()) - - if (elem == ret._M_cmpts.begin()) - ret.clear(); - else - { - ret._M_pathname.erase(elem->_M_pos); - // Remove empty filename at the end: - ret._M_cmpts.pop_back(); - // If we still have a trailing non-root dir separator - // then leave an empty filename at the end: - if (std::prev(elem)->_M_type() == _Type::_Filename) - elem->clear(); - else // remove the component completely: - ret._M_cmpts.pop_back(); - } - } - else - // Append the ".." to something ending in "../" which happens - // when normalising paths like ".././.." and "../a/../.." - ret /= p; - } - } - else if (is_dot(p)) - ret /= path(); -#if SLASHSLASH_IS_ROOTNAME - else if (p._M_type() == _Type::_Root_dir) - ret += '/'; // using operator/=('/') would replace whole of ret -#endif - else - ret /= p; - } - - if (ret._M_cmpts.size() >= 2) - { - auto back = std::prev(ret.end()); - // If the last filename is dot-dot, ... - if (back->empty() && is_dotdot(*std::prev(back))) - // ... remove any trailing directory-separator. - ret = ret.parent_path(); - } - // If the path is empty, add a dot. - else if (ret.empty()) - ret = "."; - - return ret; -} - -path -path::lexically_relative(const path& base) const -{ - path ret; - if (root_name() != base.root_name()) - return ret; - if (is_absolute() != base.is_absolute()) - return ret; - if (!has_root_directory() && base.has_root_directory()) - return ret; - auto [a, b] = std::mismatch(begin(), end(), base.begin(), base.end()); - if (a == end() && b == base.end()) - ret = "."; - else - { - int n = 0; - for (; b != base.end(); ++b) - { - const path& p = *b; - if (is_dotdot(p)) - --n; - else if (!p.empty() && !is_dot(p)) - ++n; - } - if (n == 0 && (a == end() || a->empty())) - ret = "."; - else if (n >= 0) - { - const path dotdot(".."); - while (n--) - ret /= dotdot; - for (; a != end(); ++a) - ret /= *a; - } - } - return ret; -} - -path -path::lexically_proximate(const path& base) const -{ - path rel = lexically_relative(base); - if (rel.empty()) - rel = *this; - return rel; -} - -std::pair -path::_M_find_extension() const -{ - const string_type* s = nullptr; - - if (_M_type() == _Type::_Filename) - s = &_M_pathname; - else if (_M_type() == _Type::_Multi && !_M_cmpts.empty()) - { - const auto& c = _M_cmpts.back(); - if (c._M_type() == _Type::_Filename) - s = &c._M_pathname; - } - - if (s) - { - if (auto sz = s->size()) - { - if (sz <= 2 && (*s)[0] == dot) - return { s, string_type::npos }; - const auto pos = s->rfind(dot); - return { s, pos ? pos : string_type::npos }; - } - } - return {}; -} - -void -path::_M_split_cmpts() -{ - _M_cmpts.clear(); - - if (_M_pathname.empty()) - { - _M_cmpts.type(_Type::_Filename); - return; - } - if (_M_pathname.length() == 1 && _M_pathname[0] == preferred_separator) - { - _M_cmpts.type(_Type::_Root_dir); - return; - } - - _Parser parser(_M_pathname); - - std::array<_Parser::cmpt, 64> buf; - auto next = buf.begin(); - - // look for root name or root directory - auto root_path = parser.root_path(); - if (root_path.first.valid()) - { - *next++ = root_path.first; - if (root_path.second.valid()) - *next++ = root_path.second; - } - - auto cmpt = parser.next(); - while (cmpt.valid()) - { - do - { - *next++ = cmpt; - cmpt = parser.next(); - } - while (cmpt.valid() && next != buf.end()); - - if (next == buf.end()) - { - _M_cmpts.type(_Type::_Multi); - _M_cmpts.reserve(_M_cmpts.size() + buf.size()); - auto output = _M_cmpts._M_impl->end(); - for (auto& c : buf) - { - auto pos = c.str.data() - _M_pathname.data(); - ::new(output++) _Cmpt(c.str, c.type, pos); - ++_M_cmpts._M_impl->_M_size; - } - next = buf.begin(); - } - } - - if (auto n = next - buf.begin()) - { - if (n == 1 && _M_cmpts.empty()) - { - _M_cmpts.type(buf.front().type); - return; - } - - _M_cmpts.type(_Type::_Multi); - _M_cmpts.reserve(_M_cmpts.size() + n, true); - auto output = _M_cmpts._M_impl->end(); - for (int i = 0; i < n; ++i) - { - auto c = buf[i]; - auto pos = c.str.data() - _M_pathname.data(); - ::new(output++) _Cmpt(c.str, c.type, pos); - ++_M_cmpts._M_impl->_M_size; - } - } -} - -path::string_type -path::_S_convert_loc(const char* __first, const char* __last, - const std::locale& __loc) -{ -#if _GLIBCXX_USE_WCHAR_T - auto& __cvt = std::use_facet>(__loc); - basic_string __ws; - if (!__str_codecvt_in(__first, __last, __ws, __cvt)) - _GLIBCXX_THROW_OR_ABORT(filesystem_error( - "Cannot convert character sequence", - std::make_error_code(errc::illegal_byte_sequence))); -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - return __ws; -#else - return _Cvt::_S_convert(__ws.data(), __ws.data() + __ws.size()); -#endif -#else - return {__first, __last}; -#endif -} - -std::size_t -fs::hash_value(const path& p) noexcept -{ - // [path.non-member] - // "If for two paths, p1 == p2 then hash_value(p1) == hash_value(p2)." - // Equality works as if by traversing the range [begin(), end()), meaning - // e.g. path("a//b") == path("a/b"), so we cannot simply hash _M_pathname - // but need to iterate over individual elements. Use the hash_combine from - // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3876.pdf - size_t seed = 0; - for (const auto& x : p) - { - seed ^= std::hash()(x.native()) + 0x9e3779b9 - + (seed<<6) + (seed>>2); - } - return seed; -} - -struct fs::filesystem_error::_Impl -{ - _Impl(const string& what_arg, const path& p1, const path& p2) - : path1(p1), path2(p2), what(make_what(what_arg, &p1, &p2)) - { } - - _Impl(const string& what_arg, const path& p1) - : path1(p1), path2(), what(make_what(what_arg, &p1, nullptr)) - { } - - _Impl(const string& what_arg) - : what(make_what(what_arg, nullptr, nullptr)) - { } - - static std::string - make_what(const std::string& s, const path* p1, const path* p2) - { - const std::string pstr1 = p1 ? p1->u8string() : std::string{}; - const std::string pstr2 = p2 ? p2->u8string() : std::string{}; - const size_t len = 18 + s.length() - + (pstr1.length() ? pstr1.length() + 3 : 0) - + (pstr2.length() ? pstr2.length() + 3 : 0); - std::string w; - w.reserve(len); - w = "filesystem error: "; - w += s; - if (p1) - { - w += " ["; - w += pstr1; - w += ']'; - if (p2) - { - w += " ["; - w += pstr2; - w += ']'; - } - } - return w; - } - - path path1; - path path2; - std::string what; -}; - -template class std::__shared_ptr; - -fs::filesystem_error:: -filesystem_error(const string& what_arg, error_code ec) -: system_error(ec, what_arg), - _M_impl(std::__make_shared<_Impl>(what_arg)) -{ } - -fs::filesystem_error:: -filesystem_error(const string& what_arg, const path& p1, error_code ec) -: system_error(ec, what_arg), - _M_impl(std::__make_shared<_Impl>(what_arg, p1)) -{ } - -fs::filesystem_error:: -filesystem_error(const string& what_arg, const path& p1, const path& p2, - error_code ec) -: system_error(ec, what_arg), - _M_impl(std::__make_shared<_Impl>(what_arg, p1, p2)) -{ } - -fs::filesystem_error::~filesystem_error() = default; - -const fs::path& -fs::filesystem_error::path1() const noexcept -{ return _M_impl->path1; } - -const fs::path& -fs::filesystem_error::path2() const noexcept -{ return _M_impl->path2; } - -const char* -fs::filesystem_error::what() const noexcept -{ return _M_impl->what.c_str(); } diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/append/path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/append/path.cc index 3375b065181..93c0f15f5ea 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/append/path.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/append/path.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/append/source.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/append/source.cc index a73766ce307..db80087ba6c 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/append/source.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/append/source.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2018-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/assign/assign.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/assign/assign.cc index b93543c41df..13828fe9550 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/assign/assign.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/assign/assign.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/assign/copy.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/assign/copy.cc index e182d1ae21a..6c24e3ae7b9 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/assign/copy.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/assign/copy.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/compare/compare.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/compare/compare.cc index b24527312e0..7ce16f4d190 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/compare/compare.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/compare/compare.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/compare/lwg2936.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/compare/lwg2936.cc index e45f9366c8e..bcb99cc6ddc 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/compare/lwg2936.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/compare/lwg2936.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/compare/path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/compare/path.cc index b46ff703bcb..4de5a789994 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/compare/path.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/compare/path.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/compare/strings.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/compare/strings.cc index f12b68fb019..3f0aa4bde06 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/compare/strings.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/compare/strings.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/concat/path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/concat/path.cc index e2a14bd8fcc..9f534e64cb7 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/concat/path.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/concat/path.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/concat/strings.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/concat/strings.cc index 21e2ecdfcaf..80ce25ef119 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/concat/strings.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/concat/strings.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/80762.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/80762.cc index 5bf8298a818..71cdaa9d969 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/80762.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/80762.cc @@ -17,7 +17,6 @@ // { dg-options "-std=gnu++17" } // { dg-do compile { target c++17 } } -// { dg-require-filesystem-ts "" } #include diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/copy.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/copy.cc index 5bab635eb1a..b29ab34332e 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/copy.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/copy.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/default.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/default.cc index 2280e7de64a..1e49c681a34 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/default.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/default.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/format.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/format.cc index b97305b2aa6..f80d9860496 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/format.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/format.cc @@ -15,9 +15,8 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } #include #include diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/locale.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/locale.cc index 12b437c37b0..bfb8aa136ea 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/locale.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/locale.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/range.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/range.cc index 6b447980129..f7a40364b8a 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/range.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/range.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/string_view.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/string_view.cc index 42340e6eb75..343928edde6 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/construct/string_view.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/construct/string_view.cc @@ -1,6 +1,5 @@ -// { dg-options "-lstdc++fs -std=gnu++17" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2016-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/extension.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/extension.cc index d3f8d7e3c54..a4d48c96eda 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/extension.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/extension.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/filename.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/filename.cc index 51c4773a8db..1bda26f088a 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/filename.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/filename.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/parent_path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/parent_path.cc index 33f645fd649..a49419f19dc 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/parent_path.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/parent_path.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/relative_path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/relative_path.cc index 58a5c915e52..b1e9b1d7a9f 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/relative_path.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/relative_path.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc index f799faede21..f171425f8a6 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_name.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_name.cc index ce0d1335ca9..eb8e416eddb 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_name.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_name.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_path.cc index 917f1a3842c..4f4c531819f 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_path.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_path.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/stem.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/stem.cc index 705fff89b8b..3320e7aca3e 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/stem.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/stem.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc index 844168352c8..c93a1245b70 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal.cc @@ -15,9 +15,8 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } #include #include diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal2.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal2.cc index f78f5dd8a9f..8c5bb954e81 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal2.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/normal2.cc @@ -15,9 +15,8 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } #undef _GLIBCXX_USE_CXX11_ABI #define _GLIBCXX_USE_CXX11_ABI 0 diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/proximate.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/proximate.cc index 01b548bf5ef..1d666791001 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/proximate.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/proximate.cc @@ -15,9 +15,8 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } #include #include diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/relative.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/relative.cc index 0bf8d34dbe0..dde08d46f2c 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/generation/relative.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generation/relative.cc @@ -15,9 +15,8 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } #include #include diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc index 60e53fec2aa..5a0c24c25c3 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2017-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/itr/components.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/itr/components.cc index 70eba60b34e..51583dd55b5 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/itr/components.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/itr/components.cc @@ -15,9 +15,8 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } #include #include diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/itr/traversal.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/itr/traversal.cc index 16147ca8c28..8513021e729 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/itr/traversal.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/itr/traversal.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/clear.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/clear.cc index 65c2c4c049b..3fa89938d7d 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/clear.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/clear.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/make_preferred.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/make_preferred.cc index 2c514b4caff..e49c08e8032 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/make_preferred.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/make_preferred.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/remove_filename.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/remove_filename.cc index 53423155a75..3b2ef062b6f 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/remove_filename.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/remove_filename.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_extension.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_extension.cc index b0f6ff70eab..df4b77aa116 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_extension.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_extension.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_filename.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_filename.cc index 52e438096b8..6503454e303 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_filename.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/replace_filename.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/swap.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/swap.cc index 34ae9262a8b..7414b8078b4 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/swap.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/modifiers/swap.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/native/string.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/native/string.cc index 853eb70d0d2..5417ab4c011 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/native/string.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/native/string.cc @@ -15,9 +15,8 @@ // with this library; see the file COPYING3. If not see // . -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } #include #include diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/nonmember/append.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/nonmember/append.cc index 8c16f60bdad..d4e1d6fb5f6 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/nonmember/append.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/nonmember/append.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2018-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/nonmember/hash_value.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/nonmember/hash_value.cc index f8614d85656..13a0767a9eb 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/nonmember/hash_value.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/nonmember/hash_value.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/empty.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/empty.cc index f176ef61848..7d0dc9bf8cc 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/empty.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/empty.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_extension.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_extension.cc index a18fee6808f..870d585a173 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_extension.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_extension.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_filename.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_filename.cc index d58cc2760fd..7e6981130ea 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_filename.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_filename.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_parent_path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_parent_path.cc index 2d0b52ac315..17bbaba6310 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_parent_path.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_parent_path.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_relative_path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_relative_path.cc index 3af632badf1..42b1758d18a 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_relative_path.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_relative_path.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_directory.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_directory.cc index 4df0054f518..d7f09b3f4b3 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_directory.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_directory.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_name.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_name.cc index bda2c1c938a..15ab315bc93 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_name.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_name.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_path.cc index f5daabc9d2a..a5742ca4d77 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_path.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_root_path.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_stem.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_stem.cc index e3366763e9b..09714994185 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_stem.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/has_stem.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/is_absolute.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/is_absolute.cc index a48d3206eeb..ac97eee5115 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/is_absolute.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/is_absolute.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2018-2019 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/query/is_relative.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/query/is_relative.cc index 3f7317286e1..61bbd57edec 100644 --- a/libstdc++-v3/testsuite/27_io/filesystem/path/query/is_relative.cc +++ b/libstdc++-v3/testsuite/27_io/filesystem/path/query/is_relative.cc @@ -1,6 +1,5 @@ -// { dg-options "-std=gnu++17 -lstdc++fs" } +// { dg-options "-std=gnu++17" } // { dg-do run { target c++17 } } -// { dg-require-filesystem-ts "" } // Copyright (C) 2014-2019 Free Software Foundation, Inc. //