Clang: Fix error when including float.h with mingw

Prevent mingw from trying to #include_next a private header from a path
we cannot add to our list of includes.

Fixes: QTCREATORBUG-24251
Task-number: QTCREATORBUG-24027
Change-Id: I18a9db130b9c2265cd208c3506d08d2e1c4cee45
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
This commit is contained in:
Christian Kandeler
2020-07-09 09:44:39 +02:00
parent d964e91432
commit 782ca5d8d8
4 changed files with 104 additions and 17 deletions

View File

@@ -0,0 +1,34 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
// MinGW's "public" float.h includes a "private" float.h via #include_next.
// We don't have access to the private header, because we cannot add its directory to
// the list of include paths due to other headers in there that confuse clang.
// Therefore, we prevent inclusion of the private header by setting a magic macro.
// See also QTCREATORBUG-24251.
#ifdef __MINGW32__ // Redundant, but let's play it safe.
#define __FLOAT_H
#include_next <float.h>
#endif

View File

@@ -155,6 +155,7 @@ QStringList CompilerOptionsBuilder::build(ProjectFile::Kind fileKind,
addExtraOptions();
insertWrappedQtHeaders();
insertWrappedMingwHeaders();
return options();
}
@@ -285,6 +286,16 @@ void CompilerOptionsBuilder::enableExceptions()
add("-fexceptions");
}
void CompilerOptionsBuilder::insertWrappedQtHeaders()
{
insertWrappedHeaders(wrappedQtHeadersIncludePath());
}
void CompilerOptionsBuilder::insertWrappedMingwHeaders()
{
insertWrappedHeaders(wrappedMingwHeadersIncludePath());
}
static QString creatorResourcePath()
{
#ifndef UNIT_TESTS
@@ -294,19 +305,26 @@ static QString creatorResourcePath()
#endif
}
void CompilerOptionsBuilder::insertWrappedQtHeaders()
void CompilerOptionsBuilder::insertWrappedHeaders(const QStringList &relPaths)
{
if (m_useTweakedHeaderPaths == UseTweakedHeaderPaths::No)
return;
if (relPaths.isEmpty())
return;
QStringList wrappedQtHeaders;
addWrappedQtHeadersIncludePath(wrappedQtHeaders);
QStringList args;
for (const QString &relPath : relPaths) {
static const QString baseDir = creatorResourcePath() + "/cplusplus";
const QString fullPath = baseDir + '/' + relPath;
QTC_ASSERT(QDir(fullPath).exists(), continue);
args << includeUserPathOption << QDir::toNativeSeparators(fullPath);
}
const int index = m_options.indexOf(QRegularExpression("\\A-I.*\\z"));
if (index < 0)
add(wrappedQtHeaders);
add(args);
else
m_options = m_options.mid(0, index) + wrappedQtHeaders + m_options.mid(index);
m_options = m_options.mid(0, index) + args + m_options.mid(index);
}
void CompilerOptionsBuilder::addHeaderPathOptions()
@@ -686,19 +704,18 @@ bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro
return false;
}
void CompilerOptionsBuilder::addWrappedQtHeadersIncludePath(QStringList &list) const
QStringList CompilerOptionsBuilder::wrappedQtHeadersIncludePath() const
{
static const QString resourcePath = creatorResourcePath();
static QString wrappedQtHeadersPath = resourcePath + "/cplusplus/wrappedQtHeaders";
QTC_ASSERT(QDir(wrappedQtHeadersPath).exists(), return;);
if (m_projectPart.qtVersion == Utils::QtVersion::None)
return {};
return {"wrappedQtHeaders", "wrappedQtHeaders/QtCore"};
}
if (m_projectPart.qtVersion != Utils::QtVersion::None) {
const QString wrappedQtCoreHeaderPath = wrappedQtHeadersPath + "/QtCore";
list.append({includeUserPathOption,
QDir::toNativeSeparators(wrappedQtHeadersPath),
includeUserPathOption,
QDir::toNativeSeparators(wrappedQtCoreHeaderPath)});
}
QStringList CompilerOptionsBuilder::wrappedMingwHeadersIncludePath() const
{
if (m_projectPart.toolchainType != ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID)
return {};
return {"wrappedMingwHeaders"};
}
void CompilerOptionsBuilder::addProjectConfigFileInclude()

View File

@@ -71,6 +71,7 @@ public:
void addCompilerFlags();
void enableExceptions();
void insertWrappedQtHeaders();
void insertWrappedMingwHeaders();
void addLanguageVersionAndExtensions();
void updateFileLanguage(ProjectFile::Kind fileKind);
@@ -97,7 +98,9 @@ public:
private:
void addIncludeDirOptionForPath(const ProjectExplorer::HeaderPath &path);
bool excludeDefineDirective(const ProjectExplorer::Macro &macro) const;
void addWrappedQtHeadersIncludePath(QStringList &list) const;
void insertWrappedHeaders(const QStringList &paths);
QStringList wrappedQtHeadersIncludePath() const;
QStringList wrappedMingwHeadersIncludePath() const;
QByteArray msvcVersion() const;
private:

View File

@@ -475,6 +475,39 @@ TEST_F(CompilerOptionsBuilder, InsertWrappedQtHeaders)
ASSERT_THAT(compilerOptionsBuilder.options(), Contains(IsPartOfHeader("wrappedQtHeaders")));
}
TEST_F(CompilerOptionsBuilder, InsertWrappedMingwHeadersWithNonMingwToolchain)
{
CppTools::CompilerOptionsBuilder builder{
projectPart,
CppTools::UseSystemHeader::Yes,
CppTools::UseTweakedHeaderPaths::Yes,
CppTools::UseLanguageDefines::No,
CppTools::UseBuildSystemWarnings::No,
"dummy_version",
""};
builder.insertWrappedMingwHeaders();
ASSERT_THAT(builder.options(), Not(Contains(IsPartOfHeader("wrappedMingwHeaders"))));
}
TEST_F(CompilerOptionsBuilder, InsertWrappedMingwHeadersWithMingwToolchain)
{
CppTools::CompilerOptionsBuilder builder{
projectPart,
CppTools::UseSystemHeader::Yes,
CppTools::UseTweakedHeaderPaths::Yes,
CppTools::UseLanguageDefines::No,
CppTools::UseBuildSystemWarnings::No,
"dummy_version",
""};
projectPart.toolchainType = ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID;
builder.insertWrappedMingwHeaders();
ASSERT_THAT(builder.options(), Contains(IsPartOfHeader("wrappedMingwHeaders")));
}
TEST_F(CompilerOptionsBuilder, SetLanguageVersion)
{
compilerOptionsBuilder.updateFileLanguage(ProjectFile::CXXSource);