Skip to content

Conversation

@Lachlan-Frawley
Copy link

@Lachlan-Frawley Lachlan-Frawley commented Oct 20, 2025

Fix libclang finding the wrong resource paths by giving clang_parseTranslationUnit2() the path to libclang instead of just 'clang'.

Seems related to #18150 and #51256

Minimal example repo: https://github.com/Lachlan-Frawley/libclang-resource-path-minimal-example

Having thought about this a bit, I've considered it might be the wrong approach to solve the problem, but it does work.

Before fix is applied (showing bad resource paths):

clang version 22.0.0git (https://github.com/Lachlan-Frawley/llvm-project.git 5b5eacc5790365b90878a79893325bfae00ed693)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir:
Found candidate GCC installation: /../lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /../lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /../lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Candidate multilib: x32;@mx32
Selected multilib: .;@m64
ignoring nonexistent directory "lib/clang/22/include"
ignoring nonexistent directory "/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
my-cpp-header.h:4:10: fatal error: 'cstdint' file not found
MY_CONSTEXPR_VALUE -> 0

After changes here are applied (correct resource paths):

clang version 22.0.0git (https://github.com/Lachlan-Frawley/llvm-project.git 5b5eacc5790365b90878a79893325bfae00ed693)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/workspace/clang-mre/llvm-project/build/lib
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Candidate multilib: x32;@mx32
Selected multilib: .;@m64
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
 /home/workspace/clang-mre/llvm-project/build/lib/../include/x86_64-unknown-linux-gnu/c++/v1
 /home/workspace/clang-mre/llvm-project/build/lib/../include/c++/v1
 /home/workspace/clang-mre/llvm-project/build/lib/clang/22/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
MY_CONSTEXPR_VALUE -> 6

…clang correctly determines its resource paths. Also add a new function to explicitly get libclangs path.
@github-actions
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:as-a-library libclang and C++ API labels Oct 20, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 20, 2025

@llvm/pr-subscribers-clang

Author: Lachlan Frawley (Lachlan-Frawley)

Changes

Fix clang finding the wrong resource paths by giving clang_parseTranslationUnit2() the path to libclang instead of just 'clang'.

Seems related to #18150 and #51256

Minimal example repo: https://github.com/Lachlan-Frawley/libclang-resource-path-minimal-example

Having thought about this a bit, I've considered it might be the wrong approach to solve the problem, but it does work.

Before fix is applied (showing bad resource paths):

clang version 22.0.0git (https://github.com/Lachlan-Frawley/llvm-project.git 5b5eacc5790365b90878a79893325bfae00ed693)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir:
Found candidate GCC installation: /../lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /../lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /../lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@<!-- -->m64
Candidate multilib: 32;@<!-- -->m32
Candidate multilib: x32;@<!-- -->mx32
Selected multilib: .;@<!-- -->m64
ignoring nonexistent directory "lib/clang/22/include"
ignoring nonexistent directory "/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include &lt;...&gt; search starts here:
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
my-cpp-header.h:4:10: fatal error: 'cstdint' file not found
MY_CONSTEXPR_VALUE -&gt; 0

After changes here are applied (correct resource paths):

clang version 22.0.0git (https://github.com/Lachlan-Frawley/llvm-project.git 5b5eacc5790365b90878a79893325bfae00ed693)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/workspace/clang-mre/llvm-project/build/lib
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@<!-- -->m64
Candidate multilib: 32;@<!-- -->m32
Candidate multilib: x32;@<!-- -->mx32
Selected multilib: .;@<!-- -->m64
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include &lt;...&gt; search starts here:
 /home/workspace/clang-mre/llvm-project/build/lib/../include/x86_64-unknown-linux-gnu/c++/v1
 /home/workspace/clang-mre/llvm-project/build/lib/../include/c++/v1
 /home/workspace/clang-mre/llvm-project/build/lib/clang/22/include
 /usr/local/include
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
MY_CONSTEXPR_VALUE -&gt; 6

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

3 Files Affected:

  • (modified) clang/tools/libclang/CIndex.cpp (+5-1)
  • (modified) clang/tools/libclang/CIndexer.cpp (+22-9)
  • (modified) clang/tools/libclang/CIndexer.h (+4)
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index fc27fd29da933..9d74ee61473eb 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -4414,7 +4414,11 @@ enum CXErrorCode clang_parseTranslationUnit2(
     unsigned options, CXTranslationUnit *out_TU) {
   noteBottomOfStack();
   SmallVector<const char *, 4> Args;
-  Args.push_back("clang");
+
+  CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+  auto library_path = CXXIdx->getLibClangPath();
+  Args.push_back(library_path.c_str());
+
   Args.append(command_line_args, command_line_args + num_command_line_args);
   return clang_parseTranslationUnit2FullArgv(
       CIdx, source_filename, Args.data(), Args.size(), unsaved_files,
diff --git a/clang/tools/libclang/CIndexer.cpp b/clang/tools/libclang/CIndexer.cpp
index 11d9312b64849..fbb9342800ac8 100644
--- a/clang/tools/libclang/CIndexer.cpp
+++ b/clang/tools/libclang/CIndexer.cpp
@@ -96,7 +96,21 @@ const std::string &CIndexer::getClangResourcesPath() {
   if (!ResourcesPath.empty())
     return ResourcesPath;
 
-  SmallString<128> LibClangPath;
+  if (CachedLibClangPath.empty())
+    getLibClangPath();
+
+  // Cache our result.
+  ResourcesPath = driver::Driver::GetResourcesPath(CachedLibClangPath);
+  return ResourcesPath;
+}
+
+const std::string &CIndexer::getLibClangPath()
+{
+  // Did we already compute the path?
+  if (!CachedLibClangPath.empty())
+    return CachedLibClangPath;
+
+  SmallString<128> ResultPath;
 
   // Find the location where this library lives (libclang.dylib).
 #ifdef _WIN32
@@ -106,9 +120,9 @@ const std::string &CIndexer::getClangResourcesPath() {
                sizeof(mbi));
   GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);
 
-  LibClangPath += path;
+  ResultPath += path;
 #elif defined(_AIX)
-  getClangResourcesPathImplAIX(LibClangPath);
+  getClangResourcesPathImplAIX(ResultPath);
 #else
   bool PathFound = false;
 #if defined(CLANG_HAVE_DLFCN_H) && defined(CLANG_HAVE_DLADDR)
@@ -116,7 +130,7 @@ const std::string &CIndexer::getClangResourcesPath() {
   // This silly cast below avoids a C++ warning.
   if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) != 0) {
     // We now have the CIndex directory, locate clang relative to it.
-    LibClangPath += info.dli_fname;
+    ResultPath += info.dli_fname;
     PathFound = true;
   }
 #endif
@@ -126,19 +140,18 @@ const std::string &CIndexer::getClangResourcesPath() {
       // If we can't get the path using dladdr, try to get the main executable
       // path. This may be needed when we're statically linking libclang with
       // musl libc, for example.
-      LibClangPath += Path;
+      ResultPath += Path;
     } else {
       // It's rather unlikely we end up here. But it could happen, so report an
       // error instead of crashing.
-      llvm::report_fatal_error("could not locate Clang resource path");
+      llvm::report_fatal_error("could not locate libclang path");
     }
   }
 
 #endif
 
-  // Cache our result.
-  ResourcesPath = driver::Driver::GetResourcesPath(LibClangPath);
-  return ResourcesPath;
+  CachedLibClangPath = std::string(ResultPath);
+  return CachedLibClangPath;
 }
 
 StringRef CIndexer::getClangToolchainPath() {
diff --git a/clang/tools/libclang/CIndexer.h b/clang/tools/libclang/CIndexer.h
index 83268a2016c8f..226fa5bf6e3f1 100644
--- a/clang/tools/libclang/CIndexer.h
+++ b/clang/tools/libclang/CIndexer.h
@@ -37,6 +37,7 @@ class CIndexer {
   bool StorePreamblesInMemory = false;
   unsigned Options; // CXGlobalOptFlags.
 
+  std::string CachedLibClangPath;
   std::string ResourcesPath;
   std::shared_ptr<PCHContainerOperations> PCHContainerOps;
 
@@ -77,6 +78,9 @@ class CIndexer {
   /// Get the path of the clang resource files.
   const std::string &getClangResourcesPath();
 
+  /// Get the path of libclang.
+  const std::string &getLibClangPath();
+
   StringRef getClangToolchainPath();
 
   void setStorePreamblesInMemory(bool StoreInMemory) {

@Lachlan-Frawley Lachlan-Frawley changed the title Fix clang finding the wrong resource paths Fix libclang finding the wrong resource paths Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:as-a-library libclang and C++ API clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants