Skip to content

Driver: Avoid llvm::sys::path::append if resource directory absolute. #146449

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

pcc
Copy link
Contributor

@pcc pcc commented Jul 1, 2025

After #145996 CLANG_RESOURCE_DIR can be an absolute path so we need to
handle it correctly in the driver.

llvm::sys::path::append does not append absolute paths in the way
that I expected (or consistent with other similar APIs such as C++17
std::filesystem::path::append or Python os.path.join); instead, it
effectively discards the leading / and appends the resulting relative path
(e.g. append(P, "/bar") with P = "/foo" sets P to "/foo/bar").

Many tests start failing if I try to align llvm::sys::path::append with
the other APIs because of callers that expect the existing behavior,
so for now let's add a special case here for absolute resource paths,
and document the behavior in Path.h.

Created using spr 1.3.6-beta.1
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' llvm:support labels Jul 1, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 1, 2025

@llvm/pr-subscribers-llvm-support

Author: Peter Collingbourne (pcc)

Changes

llvm::sys::path::append does not append absolute paths in the way
that I expected (or consistent with other similar APIs such as C++17
std::filesystem::path::append or Python os.path.join); instead, it
effectively discards the leading / and appends the resulting relative path
(e.g. append(P, "/bar") with P = "/foo" sets P to "/foo/bar").

Many tests start failing if I try to align llvm::sys::path::append with
the other APIs because of callers that expect the existing behavior,
so for now let's add a special case here for absolute resource paths,
and document the behavior in Path.h.


Full diff: https://github.com/llvm/llvm-project/pull/146449.diff

2 Files Affected:

  • (modified) clang/lib/Driver/Driver.cpp (+6-1)
  • (modified) llvm/include/llvm/Support/Path.h (+1)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 775f3f029861c..d86f47bada86b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -192,7 +192,12 @@ std::string Driver::GetResourcesPath(StringRef BinaryPath) {
 
   StringRef ConfiguredResourceDir(CLANG_RESOURCE_DIR);
   if (!ConfiguredResourceDir.empty()) {
-    llvm::sys::path::append(P, ConfiguredResourceDir);
+    // FIXME: We should fix the behavior of llvm::sys::path::append so we don't
+    // need to check for absolute paths here.
+    if (llvm::sys::path::is_absolute(ConfiguredResourceDir))
+      P = ConfiguredResourceDir;
+    else
+      llvm::sys::path::append(P, ConfiguredResourceDir);
   } else {
     // On Windows, libclang.dll is in bin/.
     // On non-Windows, libclang.so/.dylib is in lib/.
diff --git a/llvm/include/llvm/Support/Path.h b/llvm/include/llvm/Support/Path.h
index 0d8881359b806..ee8b1779b68ad 100644
--- a/llvm/include/llvm/Support/Path.h
+++ b/llvm/include/llvm/Support/Path.h
@@ -223,6 +223,7 @@ LLVM_ABI bool remove_dots(SmallVectorImpl<char> &path,
 ///   /foo  + bar/f => /foo/bar/f
 ///   /foo/ + bar/f => /foo/bar/f
 ///   foo   + bar/f => foo/bar/f
+///   foo   + /bar/f => foo/bar/f (FIXME: will be changed to /bar/f to align with C++17 std::filesystem::path::append)
 /// @endcode
 ///
 /// @param path Set to \a path + \a component.

@llvmbot
Copy link
Member

llvmbot commented Jul 1, 2025

@llvm/pr-subscribers-clang-driver

Author: Peter Collingbourne (pcc)

Changes

llvm::sys::path::append does not append absolute paths in the way
that I expected (or consistent with other similar APIs such as C++17
std::filesystem::path::append or Python os.path.join); instead, it
effectively discards the leading / and appends the resulting relative path
(e.g. append(P, "/bar") with P = "/foo" sets P to "/foo/bar").

Many tests start failing if I try to align llvm::sys::path::append with
the other APIs because of callers that expect the existing behavior,
so for now let's add a special case here for absolute resource paths,
and document the behavior in Path.h.


Full diff: https://github.com/llvm/llvm-project/pull/146449.diff

2 Files Affected:

  • (modified) clang/lib/Driver/Driver.cpp (+6-1)
  • (modified) llvm/include/llvm/Support/Path.h (+1)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 775f3f029861c..d86f47bada86b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -192,7 +192,12 @@ std::string Driver::GetResourcesPath(StringRef BinaryPath) {
 
   StringRef ConfiguredResourceDir(CLANG_RESOURCE_DIR);
   if (!ConfiguredResourceDir.empty()) {
-    llvm::sys::path::append(P, ConfiguredResourceDir);
+    // FIXME: We should fix the behavior of llvm::sys::path::append so we don't
+    // need to check for absolute paths here.
+    if (llvm::sys::path::is_absolute(ConfiguredResourceDir))
+      P = ConfiguredResourceDir;
+    else
+      llvm::sys::path::append(P, ConfiguredResourceDir);
   } else {
     // On Windows, libclang.dll is in bin/.
     // On non-Windows, libclang.so/.dylib is in lib/.
diff --git a/llvm/include/llvm/Support/Path.h b/llvm/include/llvm/Support/Path.h
index 0d8881359b806..ee8b1779b68ad 100644
--- a/llvm/include/llvm/Support/Path.h
+++ b/llvm/include/llvm/Support/Path.h
@@ -223,6 +223,7 @@ LLVM_ABI bool remove_dots(SmallVectorImpl<char> &path,
 ///   /foo  + bar/f => /foo/bar/f
 ///   /foo/ + bar/f => /foo/bar/f
 ///   foo   + bar/f => foo/bar/f
+///   foo   + /bar/f => foo/bar/f (FIXME: will be changed to /bar/f to align with C++17 std::filesystem::path::append)
 /// @endcode
 ///
 /// @param path Set to \a path + \a component.

@llvmbot
Copy link
Member

llvmbot commented Jul 1, 2025

@llvm/pr-subscribers-clang

Author: Peter Collingbourne (pcc)

Changes

llvm::sys::path::append does not append absolute paths in the way
that I expected (or consistent with other similar APIs such as C++17
std::filesystem::path::append or Python os.path.join); instead, it
effectively discards the leading / and appends the resulting relative path
(e.g. append(P, "/bar") with P = "/foo" sets P to "/foo/bar").

Many tests start failing if I try to align llvm::sys::path::append with
the other APIs because of callers that expect the existing behavior,
so for now let's add a special case here for absolute resource paths,
and document the behavior in Path.h.


Full diff: https://github.com/llvm/llvm-project/pull/146449.diff

2 Files Affected:

  • (modified) clang/lib/Driver/Driver.cpp (+6-1)
  • (modified) llvm/include/llvm/Support/Path.h (+1)
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 775f3f029861c..d86f47bada86b 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -192,7 +192,12 @@ std::string Driver::GetResourcesPath(StringRef BinaryPath) {
 
   StringRef ConfiguredResourceDir(CLANG_RESOURCE_DIR);
   if (!ConfiguredResourceDir.empty()) {
-    llvm::sys::path::append(P, ConfiguredResourceDir);
+    // FIXME: We should fix the behavior of llvm::sys::path::append so we don't
+    // need to check for absolute paths here.
+    if (llvm::sys::path::is_absolute(ConfiguredResourceDir))
+      P = ConfiguredResourceDir;
+    else
+      llvm::sys::path::append(P, ConfiguredResourceDir);
   } else {
     // On Windows, libclang.dll is in bin/.
     // On non-Windows, libclang.so/.dylib is in lib/.
diff --git a/llvm/include/llvm/Support/Path.h b/llvm/include/llvm/Support/Path.h
index 0d8881359b806..ee8b1779b68ad 100644
--- a/llvm/include/llvm/Support/Path.h
+++ b/llvm/include/llvm/Support/Path.h
@@ -223,6 +223,7 @@ LLVM_ABI bool remove_dots(SmallVectorImpl<char> &path,
 ///   /foo  + bar/f => /foo/bar/f
 ///   /foo/ + bar/f => /foo/bar/f
 ///   foo   + bar/f => foo/bar/f
+///   foo   + /bar/f => foo/bar/f (FIXME: will be changed to /bar/f to align with C++17 std::filesystem::path::append)
 /// @endcode
 ///
 /// @param path Set to \a path + \a component.

@pcc pcc requested a review from MaskRay July 1, 2025 01:20
Copy link

github-actions bot commented Jul 1, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Created using spr 1.3.6-beta.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category llvm:support
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants