1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-14 19:08:07 +08:00
Files
CMake/Source/Checks/cm_cxx_filesystem.cxx
Michael Pratt 2216843fd5 cm_cxx_filesystem: Improve detection of std::filesystem support on GCC
The check added by commit 40af103402 (cmCMakePath: do not use
std::filesystem::path with RH gcc-toolset-10, 2023-12-02, v3.28.0~5^2)
fails unnecessarily in some cases due to not inheriting
`std::string_view` publicly.

Inheritance into a class is private by default, and this std class has
public members that would be access restricted when used to create
public objects in the current scope.

On some versions of GCC, depending on standards options, this causes
either template instantiation errors, or "inaccessible base" or "not
declared" errors.

Fix by setting the inheritance to public.  This does not affect the
intention of the previous fix because the check still fails when using
gcc-toolset-10's standard library with clang.

Issue: #25458, #25453
2024-08-15 11:31:01 -04:00

74 lines
2.0 KiB
C++

#include <filesystem>
#if defined(__GLIBCXX__)
# include <string_view>
#endif
int main()
{
std::filesystem::path p0(L"/a/b/c");
std::filesystem::path p1("/a/b/c");
std::filesystem::path p2("/a/b//c");
if (p1 != p2.lexically_normal()) {
return 1;
}
#if defined(_WIN32)
// "//host/" is not preserved in some environments like GNU under MinGW.
std::filesystem::path p3("//host/a/b/../c");
if (p3.lexically_normal().generic_string() != "//host/a/c") {
return 1;
}
std::filesystem::path p4("c://a/.///b/../");
if (p4.lexically_normal().generic_string() != "c:/a/") {
return 1;
}
std::filesystem::path b1("C:\\path\\y\\..\\");
if (std::filesystem::weakly_canonical("\\\\?\\C:\\path\\x\\..") !=
b1.lexically_normal()) {
return 1;
}
#endif
// If std::string is copy-on-write, the std::filesystem::path
// implementation may accidentally trigger a reallocation and compute
// an offset between two allocations, leading to undefined behavior.
#if defined(__GLIBCXX__) && \
(!defined(_GLIBCXX_USE_CXX11_ABI) || !_GLIBCXX_USE_CXX11_ABI)
std::string p5s1 = "/path";
std::string p5s2 = std::move(p5s1);
std::filesystem::path p5 = std::string(p5s2);
p5.remove_filename();
#endif
#if defined(__GLIBCXX__)
// RH gcc-toolset-10 has a strange bug: it selects, in some circumstances,
// the wrong constructor which generate error in template instantiation.
class my_string_view : public std::string_view
{
public:
my_string_view(const char* p)
: std::string_view(p)
{
}
};
class my_path
{
public:
my_path(std::filesystem::path path) {}
my_path(my_string_view path) {}
};
my_path p{ my_string_view{ "abc" } };
// here is the bug: the constructor taking std::filesystem::path as argument
// is selected, so the compiler try to build a std::filesystem::path instance
// from the my_string_view argument and fails to do so.
#endif
return 0;
}