[PATCH] D87667: [Support/Path] Add path::is_gnu_style_absolute

Vinicius Tinti via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 14 19:25:14 PDT 2020


tinti created this revision.
tinti added reviewers: rengolin, jhenderson, kula, Bigcheese, MaskRay.
Herald added subscribers: llvm-commits, dexonsmith, hiraditya.
Herald added a project: LLVM.
tinti requested review of this revision.

Implements GNU tools IS_ABSOLUTE_PATH.

LLVM's path::is_absolute matches C++17 behavior which is not the same as
GNU tools IS_ABSOLUTE_PATH.

The key differences are:

1. Paths starting with '/' are always absolute;
2. On Windows, paths starting with '\\' are absolute;
3. On Windows, paths starting with drive letter pattern are absolute.

Drive letter pattern example "c:".

Related to PR46368.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87667

Files:
  llvm/include/llvm/Support/Path.h
  llvm/lib/Support/Path.cpp
  llvm/unittests/Support/Path.cpp


Index: llvm/unittests/Support/Path.cpp
===================================================================
--- llvm/unittests/Support/Path.cpp
+++ llvm/unittests/Support/Path.cpp
@@ -85,6 +85,25 @@
 #endif
 }
 
+TEST(is_gnu_style_absolute, Works) {
+  // Test tuple <Path, ExpectedPosixValue, ExpectedWindowsValue>.
+  SmallVector<std::tuple<StringRef, bool, bool>, 5> Paths;
+  Paths.emplace_back("", false, false);
+  Paths.emplace_back("/", true, true);
+  Paths.emplace_back("\\", false, true);
+  Paths.emplace_back("foo", false, false);
+  Paths.emplace_back("c:", false, true);
+
+  for (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<StringRef, 40> paths;
   paths.push_back("");
@@ -171,6 +190,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;
Index: llvm/lib/Support/Path.cpp
===================================================================
--- llvm/lib/Support/Path.cpp
+++ llvm/lib/Support/Path.cpp
@@ -687,6 +687,27 @@
   return !is_absolute(path, style);
 }
 
+bool is_gnu_style_absolute(const Twine &Path, Style Style) {
+  SmallString<128> PathStorage;
+  StringRef P = Path.toStringRef(PathStorage);
+
+  // Handle '/' which should be true regardless Windows or POSIX.
+  if (!P.empty() && is_separator(P.front(), Style::posix))
+    return true;
+
+  if (real_style(Style) == Style::windows) {
+    // Handle '\\' on Windows.
+    if (!P.empty() && is_separator(P.front(), Style::windows))
+      return true;
+
+    // Handle drive letter pattern (i.e "c:") on Windows.
+    if (P.size() >= 2 && (P[0] && P[1] == ':'))
+      return true;
+  }
+
+  return false;
+}
+
 StringRef remove_leading_dotslash(StringRef Path, Style style) {
   // Remove leading "./" (or ".//" or "././" etc.)
   while (Path.size() > 2 && Path[0] == '.' && is_separator(Path[1], style)) {
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?
+///
+/// LLVM \ref is_absolute matches C++17 behavior that essentially says that
+/// the path must be unambiguous (i.e. that there must be a drive letter for
+/// Windows). However GNU tools treat a path as absolute with or without the
+/// drive letter.
+///
+/// GNU style absolute define that:
+/// 1) Paths starting with '/' are always absolute;
+/// 2) On Windows, paths starting with '\\' are absolute;
+/// 3) On Windows, paths starting with drive letter pattern are absolute.
+///
+/// @param path Input path.
+/// @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.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87667.291759.patch
Type: text/x-patch
Size: 3324 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200915/41c92297/attachment.bin>


More information about the llvm-commits mailing list