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>
This commit is contained in:
Ivan Donchevskii
2018-08-23 15:45:33 +02:00
parent 4538227cb1
commit 1b4f5c0670
4 changed files with 132 additions and 64 deletions

View File

@@ -83,44 +83,17 @@ QStringList createClangOptions(const ProjectPart::Ptr &pPart, const QString &fil
return createClangOptions(pPart, fileKind); return createClangOptions(pPart, fileKind);
} }
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
}
class LibClangOptionsBuilder final : public CompilerOptionsBuilder class LibClangOptionsBuilder final : public CompilerOptionsBuilder
{ {
public: public:
LibClangOptionsBuilder(const ProjectPart &projectPart) LibClangOptionsBuilder(const ProjectPart &projectPart)
: CompilerOptionsBuilder(projectPart) : CompilerOptionsBuilder(projectPart,
, m_clangVersion(CLANG_VERSION) UseSystemHeader::No,
, m_clangResourceDirectory(CLANG_RESOURCE_DIR) QString(CLANG_VERSION),
QString(CLANG_RESOURCE_DIR))
{ {
} }
void addPredefinedHeaderPathsOptions() final
{
CompilerOptionsBuilder::addPredefinedHeaderPathsOptions();
add("-nostdinc");
add("-nostdlibinc");
addClangIncludeFolder();
addWrappedQtHeadersIncludePath();
}
void addToolchainAndProjectMacros() final void addToolchainAndProjectMacros() final
{ {
addMacros({ProjectExplorer::Macro("Q_CREATOR_RUN", "1")}); addMacros({ProjectExplorer::Macro("Q_CREATOR_RUN", "1")});
@@ -138,28 +111,6 @@ public:
} }
private: private:
void addClangIncludeFolder()
{
QTC_CHECK(!m_clangVersion.isEmpty());
add("-I");
add(clangIncludeDirectory(m_clangVersion, m_clangResourceDirectory));
}
void addWrappedQtHeadersIncludePath()
{
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";
add(includeDirOptionForPath(wrappedQtHeadersPath));
add(QDir::toNativeSeparators(wrappedQtHeadersPath));
add(includeDirOptionForPath(wrappedQtHeadersPath));
add(QDir::toNativeSeparators(wrappedQtCoreHeaderPath));
}
}
void addDummyUiHeaderOnDiskIncludePath() void addDummyUiHeaderOnDiskIncludePath()
{ {
const QString path = ModelManagerSupportClang::instance()->dummyUiHeaderOnDiskDirPath(); const QString path = ModelManagerSupportClang::instance()->dummyUiHeaderOnDiskDirPath();
@@ -168,9 +119,6 @@ private:
add(QDir::toNativeSeparators(path)); add(QDir::toNativeSeparators(path));
} }
} }
QString m_clangVersion;
QString m_clangResourceDirectory;
}; };
/** /**

View File

@@ -191,7 +191,10 @@ static AnalyzeUnits toAnalyzeUnits(const FileInfos &fileInfos)
AnalyzeUnits unitsToAnalyze; AnalyzeUnits unitsToAnalyze;
const CompilerOptionsBuilder::PchUsage pchUsage = CppTools::getPchUsage(); const CompilerOptionsBuilder::PchUsage pchUsage = CppTools::getPchUsage();
for (const FileInfo &fileInfo : fileInfos) { for (const FileInfo &fileInfo : fileInfos) {
CompilerOptionsBuilder optionsBuilder(*fileInfo.projectPart); CompilerOptionsBuilder optionsBuilder(*fileInfo.projectPart,
CppTools::UseSystemHeader::No,
QString(CLANG_VERSION),
QString(CLANG_RESOURCE_DIR));
QStringList arguments = extraClangToolsPrependOptions(); QStringList arguments = extraClangToolsPrependOptions();
arguments.append(optionsBuilder.build(fileInfo.kind, pchUsage)); arguments.append(optionsBuilder.build(fileInfo.kind, pchUsage));
arguments.append(extraClangToolsAppendOptions()); arguments.append(extraClangToolsAppendOptions());

View File

@@ -25,6 +25,8 @@
#include "compileroptionsbuilder.h" #include "compileroptionsbuilder.h"
#include "cppmodelmanager.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/vcsmanager.h> #include <coreplugin/vcsmanager.h>
@@ -40,9 +42,13 @@
namespace CppTools { namespace CppTools {
CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart, CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart,
UseSystemHeader useSystemHeader) UseSystemHeader useSystemHeader,
: m_projectPart(projectPart), QString clangVersion,
m_useSystemHeader(useSystemHeader) 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(); undefineCppLanguageFeatureMacrosForMsvc2015();
addDefineFunctionMacrosMsvc(); addDefineFunctionMacrosMsvc();
addPredefinedHeaderPathsOptions(); addGlobalUndef();
addPrecompiledHeaderOptions(pchUsage); addPrecompiledHeaderOptions(pchUsage);
addHeaderPathOptions(); addHeaderPathOptions();
addProjectConfigFileInclude(); addProjectConfigFileInclude();
@@ -78,6 +84,8 @@ QStringList CompilerOptionsBuilder::build(CppTools::ProjectFile::Kind fileKind,
addExtraOptions(); addExtraOptions();
insertPredefinedHeaderPathsOptions();
return options(); return options();
} }
@@ -509,7 +517,107 @@ bool CompilerOptionsBuilder::excludeHeaderPath(const QString &headerPath) const
return clangIncludeDir.match(headerPath).hasMatch(); 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 // In case of MSVC we need builtin clang defines to correctly handle clang includes
if (m_projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) if (m_projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)

View File

@@ -46,13 +46,15 @@ public:
}; };
CompilerOptionsBuilder(const ProjectPart &projectPart, CompilerOptionsBuilder(const ProjectPart &projectPart,
UseSystemHeader useSystemHeader = UseSystemHeader::No); UseSystemHeader useSystemHeader = UseSystemHeader::No,
QString clangVersion = QString(),
QString clangResourceDirectory = QString());
virtual ~CompilerOptionsBuilder() {} virtual ~CompilerOptionsBuilder() {}
virtual void addTargetTriple(); virtual void addTargetTriple();
virtual void addExtraCodeModelFlags(); virtual void addExtraCodeModelFlags();
virtual void enableExceptions(); virtual void enableExceptions();
virtual void addPredefinedHeaderPathsOptions(); virtual void insertPredefinedHeaderPathsOptions();
virtual void addOptionsForLanguage(bool checkForBorlandExtensions = true); virtual void addOptionsForLanguage(bool checkForBorlandExtensions = true);
virtual void updateLanguageOption(ProjectFile::Kind fileKind); virtual void updateLanguageOption(ProjectFile::Kind fileKind);
@@ -68,6 +70,7 @@ public:
// Add options based on project part // Add options based on project part
void addWordWidth(); void addWordWidth();
void addGlobalUndef();
void addHeaderPathOptions(); void addHeaderPathOptions();
void addPrecompiledHeaderOptions(PchUsage pchUsage); void addPrecompiledHeaderOptions(PchUsage pchUsage);
virtual void addToolchainAndProjectMacros(); virtual void addToolchainAndProjectMacros();
@@ -95,8 +98,14 @@ private:
QByteArray toDefineOption(const ProjectExplorer::Macro &macro) const; QByteArray toDefineOption(const ProjectExplorer::Macro &macro) const;
QString defineDirectiveToDefineOption(const ProjectExplorer::Macro &marco) const; QString defineDirectiveToDefineOption(const ProjectExplorer::Macro &marco) const;
void addClangIncludeFolder(QStringList &list);
void addWrappedQtHeadersIncludePath(QStringList &list);
QStringList m_options; QStringList m_options;
UseSystemHeader m_useSystemHeader; UseSystemHeader m_useSystemHeader;
QString m_clangVersion;
QString m_clangResourceDirectory;
}; };
} // namespace CppTools } // namespace CppTools