summaryrefslogtreecommitdiffstats
path: root/tools/libclang/CIndexer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libclang/CIndexer.cpp')
-rw-r--r--tools/libclang/CIndexer.cpp77
1 files changed, 67 insertions, 10 deletions
diff --git a/tools/libclang/CIndexer.cpp b/tools/libclang/CIndexer.cpp
index 3c6e1530f1..0054c15bc7 100644
--- a/tools/libclang/CIndexer.cpp
+++ b/tools/libclang/CIndexer.cpp
@@ -1,9 +1,8 @@
-//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
+//===- CIndexer.cpp - Clang-C Source Indexing Library ---------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -15,6 +14,7 @@
#include "CXString.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Version.h"
+#include "clang/Driver/Driver.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/MD5.h"
@@ -32,12 +32,69 @@
#ifdef _WIN32
#include <windows.h>
+#elif defined(_AIX)
+#include <errno.h>
+#include <sys/ldr.h>
#else
#include <dlfcn.h>
#endif
using namespace clang;
+#ifdef _AIX
+namespace clang {
+namespace {
+
+template <typename LibClangPathType>
+void getClangResourcesPathImplAIX(LibClangPathType &LibClangPath) {
+ int PrevErrno = errno;
+
+ size_t BufSize = 2048u;
+ std::unique_ptr<char[]> Buf;
+ while (true) {
+ Buf = llvm::make_unique<char []>(BufSize);
+ errno = 0;
+ int Ret = loadquery(L_GETXINFO, Buf.get(), (unsigned int)BufSize);
+ if (Ret != -1)
+ break; // loadquery() was successful.
+ if (errno != ENOMEM)
+ llvm_unreachable("Encountered an unexpected loadquery() failure");
+
+ // errno == ENOMEM; try to allocate more memory.
+ if ((BufSize & ~((-1u) >> 1u)) != 0u)
+ llvm::report_fatal_error("BufSize needed for loadquery() too large");
+
+ Buf.release();
+ BufSize <<= 1u;
+ }
+
+ // Extract the function entry point from the function descriptor.
+ uint64_t EntryAddr =
+ reinterpret_cast<uintptr_t &>(clang_createTranslationUnit);
+
+ // Loop to locate the function entry point in the loadquery() results.
+ ld_xinfo *CurInfo = reinterpret_cast<ld_xinfo *>(Buf.get());
+ while (true) {
+ uint64_t CurTextStart = (uint64_t)CurInfo->ldinfo_textorg;
+ uint64_t CurTextEnd = CurTextStart + CurInfo->ldinfo_textsize;
+ if (CurTextStart <= EntryAddr && EntryAddr < CurTextEnd)
+ break; // Successfully located.
+
+ if (CurInfo->ldinfo_next == 0u)
+ llvm::report_fatal_error("Cannot locate entry point in "
+ "the loadquery() results");
+ CurInfo = reinterpret_cast<ld_xinfo *>(reinterpret_cast<char *>(CurInfo) +
+ CurInfo->ldinfo_next);
+ }
+
+ LibClangPath += reinterpret_cast<char *>(CurInfo) + CurInfo->ldinfo_filename;
+ errno = PrevErrno;
+}
+
+} // end anonymous namespace
+} // end namespace clang
+#endif
+
const std::string &CIndexer::getClangResourcesPath() {
// Did we already compute the path?
if (!ResourcesPath.empty())
@@ -63,7 +120,9 @@ const std::string &CIndexer::getClangResourcesPath() {
#endif
#endif
- LibClangPath += llvm::sys::path::parent_path(path);
+ LibClangPath += path;
+#elif defined(_AIX)
+ getClangResourcesPathImplAIX(LibClangPath);
#else
// This silly cast below avoids a C++ warning.
Dl_info info;
@@ -71,13 +130,11 @@ const std::string &CIndexer::getClangResourcesPath() {
llvm_unreachable("Call to dladdr() failed");
// We now have the CIndex directory, locate clang relative to it.
- LibClangPath += llvm::sys::path::parent_path(info.dli_fname);
+ LibClangPath += info.dli_fname;
#endif
- llvm::sys::path::append(LibClangPath, "clang", CLANG_VERSION_STRING);
-
// Cache our result.
- ResourcesPath = LibClangPath.str();
+ ResourcesPath = driver::Driver::GetResourcesPath(LibClangPath);
return ResourcesPath;
}