diff --git a/plugins/clang/clangsupport.cpp b/plugins/clang/clangsupport.cpp --- a/plugins/clang/clangsupport.cpp +++ b/plugins/clang/clangsupport.cpp @@ -177,8 +177,12 @@ , m_refactoring(nullptr) , m_index(nullptr) { + clangDebug() << "Detected Clang version:" << ClangHelpers::clangVersion(); + { const auto builtinDir = ClangHelpers::clangBuiltinIncludePath(); + clangDebug() << "Using Clang builtin include path:" << builtinDir; + const auto headerToCheck = QLatin1String("cpuid.h"); if (!QFile::exists(builtinDir + QLatin1Char('/') + headerToCheck)) { setErrorDescription(i18n("The clang builtin include path \"%1\" is invalid (missing %2 header).\n" diff --git a/plugins/clang/duchain/clanghelpers.h b/plugins/clang/duchain/clanghelpers.h --- a/plugins/clang/duchain/clanghelpers.h +++ b/plugins/clang/duchain/clanghelpers.h @@ -100,6 +100,8 @@ */ KDEVCLANGPRIVATE_EXPORT bool isHeader(const QString& path); +KDEVCLANGPRIVATE_EXPORT QString clangVersion(); + /** * @return The path containing Clang built includes (e.g. stddef.h, stdarg.h, cpuid.h) * diff --git a/plugins/clang/duchain/clanghelpers.cpp b/plugins/clang/duchain/clanghelpers.cpp --- a/plugins/clang/duchain/clanghelpers.cpp +++ b/plugins/clang/duchain/clanghelpers.cpp @@ -32,11 +32,16 @@ #include "clangparsingenvironmentfile.h" #include "clangindex.h" #include "clangducontext.h" - +#include "util/clangdebug.h" #include "util/clangtypes.h" #include "libclang_include_path.h" +#include +#include +#include +#include + #include using namespace KDevelop; @@ -343,14 +348,48 @@ [&](const QString& ext) { return path.endsWith(ext); }); } +QString ClangHelpers::clangVersion() +{ + static const auto clangVersion = []() -> QString { + // NOTE: The apidocs for clang_getClangVersion() clearly state it shouldn't be used for parsing + // but there's no other way to retrieve the Clang version at runtime at this point... + const ClangString version(clang_getClangVersion()); + clangDebug() << "Full Clang version:" << version; + + // samples: + // clang version 6.0.1 (trunk 321709) (git@github.com:llvm-mirror/llvm.git 5136df4d089a086b70d452160ad5451861269498) + // clang version 7.0.0-svn341916-1~exp1~20180911115939.26 (branches/release_70) + QRegularExpression re(QStringLiteral("^clang version (\\d+\\.\\d+\\.\\d+)")); + const auto match = re.match(version.toString()); + if (!match.hasMatch()) + return {}; + + return match.captured(1); // return e.g. 7.0.0 + }(); + return clangVersion; +} + QString ClangHelpers::clangBuiltinIncludePath() { static const auto dir = []() -> QString { - auto dir = qgetenv("KDEV_CLANG_BUILTIN_DIR"); - if (dir.isEmpty()) { - dir = KDEV_CLANG_BUILTIN_DIR; + auto dir = QString::fromUtf8(qgetenv("KDEV_CLANG_BUILTIN_DIR")); + if (!dir.isEmpty()) { + clangDebug() << "Using dir from $KDEV_CLANG_BUILTIN_DIR:" << dir; + return dir; + } + +#ifdef Q_OS_WIN32 + // attempt to use the bundled copy on Windows + dir = QDir::cleanPath(QStringLiteral("%1/../lib/clang/%2/include") + .arg(QCoreApplication::applicationDirPath(), clangVersion())); + clangDebug() << "Trying" << dir; + if (QFileInfo(dir).isDir()) { + return dir; } - return QString::fromUtf8(dir); +#endif + + clangDebug() << "Using builtin dir:" << KDEV_CLANG_BUILTIN_DIR; + return QString::fromUtf8(KDEV_CLANG_BUILTIN_DIR); }(); return dir; }