diff options
author | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2018-08-23 15:45:33 +0200 |
---|---|---|
committer | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2018-08-27 11:35:02 +0000 |
commit | 1b4f5c0670aa59d703e94bff1b4181855b03f2ab (patch) | |
tree | 9b6a03422c50c44e3afa1239cbf436030644fe8b /src/plugins/cpptools/compileroptionsbuilder.cpp | |
parent | 4538227cb1abff165487dfe001eacff377dddde6 (diff) | |
download | qt-creator-1b4f5c0670aa59d703e94bff1b4181855b03f2ab.tar.gz |
Clang: Fix include paths order
C++ include paths should come before Clang include
folder. Therefore parse all options for include/c++/v1,
include/c++/{version}, include/g++ and /usr/local/include.
Task-number: QTCREATORBUG-20231
Change-Id: I22c41f07d241e1e564069bb192d4fe637ff05e87
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
Diffstat (limited to 'src/plugins/cpptools/compileroptionsbuilder.cpp')
-rw-r--r-- | src/plugins/cpptools/compileroptionsbuilder.cpp | 118 |
1 files changed, 113 insertions, 5 deletions
diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index 8a1434cce9..d63aaa0951 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -25,6 +25,8 @@ #include "compileroptionsbuilder.h" +#include "cppmodelmanager.h" + #include <coreplugin/icore.h> #include <coreplugin/vcsmanager.h> @@ -40,9 +42,13 @@ namespace CppTools { CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart, - UseSystemHeader useSystemHeader) - : m_projectPart(projectPart), - m_useSystemHeader(useSystemHeader) + UseSystemHeader useSystemHeader, + QString clangVersion, + QString clangResourceDirectory) + : m_projectPart(projectPart) + , m_useSystemHeader(useSystemHeader) + , m_clangVersion(clangVersion) + , m_clangResourceDirectory(clangResourceDirectory) { } @@ -69,7 +75,7 @@ QStringList CompilerOptionsBuilder::build(CppTools::ProjectFile::Kind fileKind, undefineCppLanguageFeatureMacrosForMsvc2015(); addDefineFunctionMacrosMsvc(); - addPredefinedHeaderPathsOptions(); + addGlobalUndef(); addPrecompiledHeaderOptions(pchUsage); addHeaderPathOptions(); addProjectConfigFileInclude(); @@ -78,6 +84,8 @@ QStringList CompilerOptionsBuilder::build(CppTools::ProjectFile::Kind fileKind, addExtraOptions(); + insertPredefinedHeaderPathsOptions(); + return options(); } @@ -509,7 +517,107 @@ bool CompilerOptionsBuilder::excludeHeaderPath(const QString &headerPath) const return clangIncludeDir.match(headerPath).hasMatch(); } -void CompilerOptionsBuilder::addPredefinedHeaderPathsOptions() +static QString creatorResourcePath() +{ +#ifndef UNIT_TESTS + return Core::ICore::resourcePath(); +#else + return QString(); +#endif +} + +static QString clangIncludeDirectory(const QString &clangVersion, + const QString &clangResourceDirectory) +{ +#ifndef UNIT_TESTS + return Core::ICore::clangIncludeDirectory(clangVersion, clangResourceDirectory); +#else + return QString(); +#endif +} + +static int lastIncludeIndex(const QStringList &options, const QRegularExpression &includePathRegEx) +{ + int index = options.lastIndexOf(includePathRegEx); + + while (index > 0 && options[index - 1] != "-I" && options[index - 1] != "-isystem") + index = options.lastIndexOf(includePathRegEx, index - 1); + + if (index == 0) + index = -1; + + return index; +} + +static int includeIndexForResourceDirectory(const QStringList &options) +{ + // include/c++/{version}, include/c++/v1 and include/g++ + const int cppIncludeIndex = lastIncludeIndex( + options, + QRegularExpression("\\A.*[\\/\\\\]include[\\/\\\\].*(g\\+\\+.*\\z|c\\+\\+[\\/\\\\](v1\\z|\\d+.*\\z))")); + + if (cppIncludeIndex > 0) + return cppIncludeIndex + 1; + + return -1; +} + +void CompilerOptionsBuilder::insertPredefinedHeaderPathsOptions() +{ + if (m_clangVersion.isEmpty()) + return; + + QStringList wrappedQtHeaders; + addWrappedQtHeadersIncludePath(wrappedQtHeaders); + + QStringList predefinedOptions; + predefinedOptions.append("-nostdinc"); + predefinedOptions.append("-nostdlibinc"); + addClangIncludeFolder(predefinedOptions); + + const int index = m_options.indexOf(QRegularExpression("\\A-I.*\\z")); + if (index < 0) { + m_options.append(wrappedQtHeaders); + m_options.append(predefinedOptions); + return; + } + + int includeIndexForResourceDir = includeIndexForResourceDirectory(m_options); + if (includeIndexForResourceDir < index) + includeIndexForResourceDir = index; + + m_options = m_options.mid(0, index) + + wrappedQtHeaders + + m_options.mid(index, includeIndexForResourceDir - index) + + predefinedOptions + + m_options.mid(includeIndexForResourceDir); +} + +void CompilerOptionsBuilder::addClangIncludeFolder(QStringList &list) +{ + QTC_CHECK(!m_clangVersion.isEmpty()); + const QString clangIncludeDir = clangIncludeDirectory(m_clangVersion, m_clangResourceDirectory); + + list.append(includeDirOptionForPath(clangIncludeDir)); + list.append(clangIncludeDir); +} + +void CompilerOptionsBuilder::addWrappedQtHeadersIncludePath(QStringList &list) +{ + static const QString resourcePath = creatorResourcePath(); + static QString wrappedQtHeadersPath = resourcePath + "/cplusplus/wrappedQtHeaders"; + QTC_ASSERT(QDir(wrappedQtHeadersPath).exists(), return;); + + if (m_projectPart.qtVersion != CppTools::ProjectPart::NoQt) { + const QString wrappedQtCoreHeaderPath = wrappedQtHeadersPath + "/QtCore"; + list.append(includeDirOptionForPath(wrappedQtHeadersPath)); + list.append(QDir::toNativeSeparators(wrappedQtHeadersPath)); + list.append(includeDirOptionForPath(wrappedQtHeadersPath)); + list.append(QDir::toNativeSeparators(wrappedQtCoreHeaderPath)); + } +} + +void CompilerOptionsBuilder::addGlobalUndef() { // In case of MSVC we need builtin clang defines to correctly handle clang includes if (m_projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) |