Index: llvm/include/llvm/Support/Path.h =================================================================== --- llvm/include/llvm/Support/Path.h +++ llvm/include/llvm/Support/Path.h @@ -455,6 +455,22 @@ /// @result True if the path is absolute, false if it is not. bool is_absolute(const Twine &path, Style style = Style::native); +/// Is path GNU style absolute? +/// +/// GNU style absolute defines the following rules: +/// 1) Paths starting with a path separator are absolute. +/// 2) Windows style paths are also absolute if they start with a character +/// followed by ':'. +/// 3) No other paths are absolute. +/// +/// LLVM \ref is_absolute rules are different. +/// +/// @param path Input path. +/// @param style The style used to define the behavior. Posix style rules are +/// different from Windows style rules. +/// @result True if the path is GNU style absolute, false if it is not. +bool is_gnu_style_absolute(const Twine &path, Style style = Style::native); + /// Is path relative? /// /// @param path Input path. Index: llvm/lib/Support/Path.cpp =================================================================== --- llvm/lib/Support/Path.cpp +++ llvm/lib/Support/Path.cpp @@ -683,6 +683,25 @@ return rootDir && rootName; } +bool is_gnu_style_absolute(const Twine &path, Style style) { + SmallString<128> path_storage; + StringRef p = path.toStringRef(path_storage); + + // Handle '/' which should be true regardless Windows or POSIX. + // Handle '\\' on Windows. + if (!p.empty() && is_separator(p.front(), style)) + return true; + + if (real_style(style) == Style::windows) { + // Handle drive letter pattern (i.e "c:") and a character followed + // by ':' on Windows. + if (p.size() >= 2 && (p[0] && p[1] == ':')) + return true; + } + + return false; +} + bool is_relative(const Twine &path, Style style) { return !is_absolute(path, style); } Index: llvm/unittests/Support/Path.cpp =================================================================== --- llvm/unittests/Support/Path.cpp +++ llvm/unittests/Support/Path.cpp @@ -85,6 +85,32 @@ #endif } +TEST(is_gnu_style_absolute, Works) { + // Test tuple . + SmallVector, 12> Paths; + Paths.emplace_back("", false, false); + Paths.emplace_back("/", true, true); + Paths.emplace_back("/foo", true, true); + Paths.emplace_back("\\", false, true); + Paths.emplace_back("\\foo", false, true); + Paths.emplace_back("foo", false, false); + Paths.emplace_back("c", false, false); + Paths.emplace_back("c:", false, true); + Paths.emplace_back("c:\\", false, true); + Paths.emplace_back("!:", false, true); + Paths.emplace_back("xx:", false, false); + Paths.emplace_back("c:abc\\", false, true); + + for (const auto &Path : Paths) { + EXPECT_EQ( + path::is_gnu_style_absolute(std::get<0>(Path), path::Style::posix), + std::get<1>(Path)); + EXPECT_EQ( + path::is_gnu_style_absolute(std::get<0>(Path), path::Style::windows), + std::get<2>(Path)); + } +} + TEST(Support, Path) { SmallVector paths; paths.push_back(""); @@ -171,6 +197,7 @@ (void)path::has_extension(*i); (void)path::extension(*i); (void)path::is_absolute(*i); + (void)path::is_gnu_style_absolute(*i); (void)path::is_relative(*i); SmallString<128> temp_store;