Bug 99333 - std::filesystem::path().is_absolute() thinks UNC paths aren't absolute
Summary: std::filesystem::path().is_absolute() thinks UNC paths aren't absolute
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 10.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-03-01 21:45 UTC by Moritz Bunkus
Modified: 2022-06-28 20:59 UTC (History)
1 user (show)

See Also:
Host:
Target: *-*-mingw*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-03-02 00:00:00


Attachments
test case (244 bytes, text/x-csrc)
2021-03-01 21:45 UTC, Moritz Bunkus
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Moritz Bunkus 2021-03-01 21:45:13 UTC
Created attachment 50280 [details]
test case

Compiling with gcc 10.2.0 from the mxe cross compilation environment for Windows.

The attached sample program says it all. It shows that std::filesystem::("\\server\share\file.txt").is_absolute() is false and turns std::filesystem::absolute("\\server\share\file.txt") into something like "C:\server\share\file.txt".

boost::filesystem::path(…).is_aboslute(), on the other hand, considers UNC paths absolute & leaves them unmodified via boost::filesystem::absolute(…)

The test program outputs the following:

std::filesystem:
  original \\disky\mosu\existing_file.txt
  is_absolute 0
  absolute "C:\\disky\\mosu\\existing_file.txt"
boost::filesystem:
  original \\disky\mosu\existing_file.txt
  is_absolute 1
  absolute "\\disky\mosu\existing_file.txt"

Compile with something like:

x86_64-w64-mingw32.static-g++ -std=c++17 \
  -I/home/mosu/prog/video/mingw/cross/usr/x86_64-w64-mingw32.static/include \
  -L/home/mosu/prog/video/mingw/cross/usr/x86_64-w64-mingw32.static/lib \
  -o std_filesystem_unc_paths_vs_absolute.exe \
  std_filesystem_unc_paths_vs_absolute.cpp \
  -lboost_filesystem-mt-s-x64 -lboost_system-mt-s-x64
Comment 1 Jonathan Wakely 2021-03-02 11:50:18 UTC
The problem is not path::is_absolute(), it's path::has_root_name(), which (by design) only handles //rootname on Cygwin:

#ifdef __CYGWIN__
// Interpret "//x" as a root-name, not root-dir + filename
# define SLASHSLASH_IS_ROOTNAME 1
#endif


I don't have boost built for mingw. Does boost recognise "//disky/mosu" as a valid path, or does a UNC root-name have to use backslashes?

i.e. is path("//disky/mosu").has_root_name() true?
Comment 2 Moritz Bunkus 2021-03-02 12:24:00 UTC
The following code tests forward & backward slashes with both std::filesystem (gcc 10.2.0, mingw via MXE) and boost::filesystem (Boost 1.74.0):

  auto slashes     = R"(//server/share/file.txt)"s;
  auto backslashes = R"(\\server\share\file.txt)"s;

  std::cout << "std::filesystem::path("   << slashes     << ").has_root_name() " << std::filesystem::path{slashes}.has_root_name()       << "\n"
            << "std::filesystem::path("   << backslashes << ").has_root_name() " << std::filesystem::path{backslashes}.has_root_name()   << "\n"
            << "boost::filesystem::path(" << slashes     << ").has_root_name() " << boost::filesystem::path{slashes}.has_root_name()     << "\n"
            << "boost::filesystem::path(" << backslashes << ").has_root_name() " << boost::filesystem::path{backslashes}.has_root_name() << "\n";

The output of that snippet is:

std::filesystem::path(//server/share/file.txt).has_root_name() 0
std::filesystem::path(\\server\share\file.txt).has_root_name() 0
boost::filesystem::path(//server/share/file.txt).has_root_name() 1
boost::filesystem::path(\\server\share\file.txt).has_root_name() 1

Or to put it differently, std::filesystem doesn't seem to care either way while Boost recognizes both.

Note that __CYGWIN__ is not defined with the compiler from MXE! I'm not compiling on Windows. This is a cross-compiler, from Linux to Windows. What is defined are things such as:

[0 mosu@sweet-chili ~] x86_64-w64-mingw32.static-g++ -dM -E -x c++ - < /dev/null | sort | grep -E 'WINNT|WIN(32|64)|MINGW'
#define __MINGW32__ 1
#define __MINGW64__ 1
#define __WIN32 1
#define __WIN32__ 1
#define _WIN32 1
#define WIN32 1
#define __WIN64 1
#define __WIN64__ 1
#define _WIN64 1
#define WIN64 1
#define __WINNT 1
#define __WINNT__ 1
#define WINNT 1
Comment 3 Jonathan Wakely 2021-03-02 13:05:14 UTC
(In reply to Moritz Bunkus from comment #2)
> while Boost recognizes both.

That's what I wanted to know, thanks.
 
> Note that __CYGWIN__ is not defined with the compiler from MXE!

Obviously, because it's not cygwin. Which is why //x paths are not treated as a root-name. As I said, that's by design, but can be changed.
Comment 4 Moritz Bunkus 2021-03-02 13:19:46 UTC
Oh right, sorry — I misread your earlier comment.
Comment 5 Jakub Jelinek 2022-05-06 08:30:33 UTC
GCC 12.1 is being released, retargeting bugs to GCC 12.2.