Clang: Forward compiler options for gcc/clang

Rely on clang to do the "right thing" with them.

Change-Id: I44adf2cd5c61549896da3fc9b7c35c2fb0142060
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Nikolai Kosjar
2019-01-08 16:22:39 +01:00
parent d52af48883
commit 4c0c3f5a64
9 changed files with 206 additions and 50 deletions

View File

@@ -76,6 +76,13 @@ QString fileInCurrentEditor()
return QString(); return QString();
} }
QSizePolicy sizePolicyWithStretchFactor(int stretchFactor)
{
QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Expanding);
policy.setHorizontalStretch(stretchFactor);
return policy;
}
class DepthFinder : public SymbolVisitor { class DepthFinder : public SymbolVisitor {
public: public:
DepthFinder() : m_symbol(0), m_depth(-1), m_foundDepth(-1), m_stop(false) {} DepthFinder() : m_symbol(0), m_depth(-1), m_foundDepth(-1), m_stop(false) {}
@@ -1357,6 +1364,9 @@ CppCodeModelInspectorDialog::CppCodeModelInspectorDialog(QWidget *parent)
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose, this, &QWidget::close); connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose, this, &QWidget::close);
m_ui->partGeneralView->setSizePolicy(sizePolicyWithStretchFactor(2));
m_ui->partGeneralCompilerFlagsEdit->setSizePolicy(sizePolicyWithStretchFactor(1));
m_proxySnapshotModel->setSourceModel(m_snapshotModel); m_proxySnapshotModel->setSourceModel(m_snapshotModel);
m_proxySnapshotModel->setFilterKeyColumn(SnapshotModel::FilePathColumn); m_proxySnapshotModel->setFilterKeyColumn(SnapshotModel::FilePathColumn);
m_snapshotView->setModel(m_proxySnapshotModel); m_snapshotView->setModel(m_proxySnapshotModel);
@@ -1815,6 +1825,9 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &
m_partGenericInfoModel->configure(table); m_partGenericInfoModel->configure(table);
resizeColumns<KeyValueModel>(m_ui->partGeneralView); resizeColumns<KeyValueModel>(m_ui->partGeneralView);
// Compiler Flags
m_ui->partGeneralCompilerFlagsEdit->setPlainText(part->compilerFlags.join("\n"));
// Project Files // Project Files
m_projectFilesModel->configure(part->files); m_projectFilesModel->configure(part->files);
m_ui->projectPartTab->setTabText(ProjectPartFilesTab, m_ui->projectPartTab->setTabText(ProjectPartFilesTab,

View File

@@ -37,9 +37,30 @@
<attribute name="title"> <attribute name="title">
<string notr="true">&amp;General</string> <string notr="true">&amp;General</string>
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_9"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<widget class="QTreeView" name="partGeneralView"/> <widget class="QTreeView" name="partGeneralView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Compiler Flags</string>
</property>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="partGeneralCompilerFlagsEdit"/>
</item>
</layout>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@@ -93,6 +93,7 @@ QStringList CompilerOptionsBuilder::build(ProjectFile::Kind fileKind,
UsePrecompiledHeaders usePrecompiledHeaders) UsePrecompiledHeaders usePrecompiledHeaders)
{ {
m_options.clear(); m_options.clear();
evaluateCompilerFlags();
if (fileKind == ProjectFile::CHeader || fileKind == ProjectFile::CSource) { if (fileKind == ProjectFile::CHeader || fileKind == ProjectFile::CSource) {
QTC_ASSERT(m_projectPart.languageVersion <= Utils::LanguageVersion::LatestC, QTC_ASSERT(m_projectPart.languageVersion <= Utils::LanguageVersion::LatestC,
@@ -108,22 +109,23 @@ QStringList CompilerOptionsBuilder::build(ProjectFile::Kind fileKind,
addWordWidth(); addWordWidth();
addTargetTriple(); addTargetTriple();
addExtraCodeModelFlags();
updateFileLanguage(fileKind); updateFileLanguage(fileKind);
addLanguageVersionAndExtensions(); addLanguageVersionAndExtensions();
addPrecompiledHeaderOptions(usePrecompiledHeaders);
addProjectConfigFileInclude();
addExtraCodeModelFlags();
addCompilerFlags();
addMsvcCompatibilityVersion();
addToolchainAndProjectMacros(); addToolchainAndProjectMacros();
undefineClangVersionMacrosForMsvc(); undefineClangVersionMacrosForMsvc();
undefineCppLanguageFeatureMacrosForMsvc2015(); undefineCppLanguageFeatureMacrosForMsvc2015();
addDefineFunctionMacrosMsvc(); addDefineFunctionMacrosMsvc();
addToolchainFlags(); addToolchainFlags();
addPrecompiledHeaderOptions(usePrecompiledHeaders);
addHeaderPathOptions(); addHeaderPathOptions();
addProjectConfigFileInclude();
addMsvcCompatibilityVersion();
addExtraOptions(); addExtraOptions();
@@ -214,6 +216,12 @@ void CompilerOptionsBuilder::addExtraCodeModelFlags()
m_options.append(m_projectPart.extraCodeModelFlags); m_options.append(m_projectPart.extraCodeModelFlags);
} }
void CompilerOptionsBuilder::addCompilerFlags()
{
if (m_compilerFlags.forward)
m_options.append(m_compilerFlags.flags);
}
static QString creatorResourcePath() static QString creatorResourcePath()
{ {
#ifndef UNIT_TESTS #ifndef UNIT_TESTS
@@ -341,48 +349,53 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
const Utils::LanguageExtensions languageExtensions = m_projectPart.languageExtensions; const Utils::LanguageExtensions languageExtensions = m_projectPart.languageExtensions;
const bool gnuExtensions = languageExtensions & LanguageExtension::Gnu; const bool gnuExtensions = languageExtensions & LanguageExtension::Gnu;
switch (m_projectPart.languageVersion) { if (!m_compilerFlags.forward
case LanguageVersion::C89: || (m_compilerFlags.forward && !m_compilerFlags.isLanguageVersionSpecified)) {
options << (gnuExtensions ? QLatin1String("-std=gnu89") : QLatin1String("-std=c89")); switch (m_projectPart.languageVersion) {
break; case LanguageVersion::C89:
case LanguageVersion::C99: options << (gnuExtensions ? QLatin1String("-std=gnu89") : QLatin1String("-std=c89"));
options << (gnuExtensions ? QLatin1String("-std=gnu99") : QLatin1String("-std=c99")); break;
break; case LanguageVersion::C99:
case LanguageVersion::C11: options << (gnuExtensions ? QLatin1String("-std=gnu99") : QLatin1String("-std=c99"));
options << (gnuExtensions ? QLatin1String("-std=gnu11") : QLatin1String("-std=c11")); break;
break; case LanguageVersion::C11:
case LanguageVersion::C18: options << (gnuExtensions ? QLatin1String("-std=gnu11") : QLatin1String("-std=c11"));
// Clang 6, 7 and current trunk do not accept "gnu18"/"c18", so use the "*17" variants. break;
options << (gnuExtensions ? QLatin1String("-std=gnu17") : QLatin1String("-std=c17")); case LanguageVersion::C18:
break; // Clang 6, 7 and current trunk do not accept "gnu18"/"c18", so use the "*17" variants.
case LanguageVersion::CXX11: options << (gnuExtensions ? QLatin1String("-std=gnu17") : QLatin1String("-std=c17"));
options << (gnuExtensions ? QLatin1String("-std=gnu++11") : QLatin1String("-std=c++11")); break;
break; case LanguageVersion::CXX11:
case LanguageVersion::CXX98: options << (gnuExtensions ? QLatin1String("-std=gnu++11") : QLatin1String("-std=c++11"));
options << (gnuExtensions ? QLatin1String("-std=gnu++98") : QLatin1String("-std=c++98")); break;
break; case LanguageVersion::CXX98:
case LanguageVersion::CXX03: options << (gnuExtensions ? QLatin1String("-std=gnu++98") : QLatin1String("-std=c++98"));
options << (gnuExtensions ? QLatin1String("-std=gnu++03") : QLatin1String("-std=c++03")); break;
break; case LanguageVersion::CXX03:
case LanguageVersion::CXX14: options << (gnuExtensions ? QLatin1String("-std=gnu++03") : QLatin1String("-std=c++03"));
options << (gnuExtensions ? QLatin1String("-std=gnu++14") : QLatin1String("-std=c++14")); break;
break; case LanguageVersion::CXX14:
case LanguageVersion::CXX17: options << (gnuExtensions ? QLatin1String("-std=gnu++14") : QLatin1String("-std=c++14"));
options << (gnuExtensions ? QLatin1String("-std=gnu++17") : QLatin1String("-std=c++17")); break;
break; case LanguageVersion::CXX17:
case LanguageVersion::CXX2a: options << (gnuExtensions ? QLatin1String("-std=gnu++17") : QLatin1String("-std=c++17"));
options << (gnuExtensions ? QLatin1String("-std=gnu++2a") : QLatin1String("-std=c++2a")); break;
break; case LanguageVersion::CXX2a:
options << (gnuExtensions ? QLatin1String("-std=gnu++2a") : QLatin1String("-std=c++2a"));
break;
}
} }
if (languageExtensions & LanguageExtension::Microsoft) if (!m_compilerFlags.forward) {
options << "-fms-extensions"; if (languageExtensions & LanguageExtension::Microsoft)
options << "-fms-extensions";
if (languageExtensions & LanguageExtension::OpenMP) if (languageExtensions & LanguageExtension::OpenMP)
options << "-fopenmp"; options << "-fopenmp";
if (languageExtensions & LanguageExtension::Borland) if (languageExtensions & LanguageExtension::Borland)
options << "-fborland-extensions"; options << "-fborland-extensions";
}
m_options.append(options); m_options.append(options);
} }
@@ -587,7 +600,7 @@ void CompilerOptionsBuilder::addToolchainFlags()
&& m_projectPart.toolchainType != ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID) { && m_projectPart.toolchainType != ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID) {
if (m_useToolchainMacros == UseToolchainMacros::Yes) if (m_useToolchainMacros == UseToolchainMacros::Yes)
add("-undef"); add("-undef");
else else if (!m_compilerFlags.forward)
add("-fPIC"); add("-fPIC");
} }
} }
@@ -632,4 +645,37 @@ void CompilerOptionsBuilder::reset()
m_options.clear(); m_options.clear();
} }
// Some example command lines for a "Qt Console Application":
// CMakeProject: -fPIC -std=gnu++11
// QbsProject: -m64 -fPIC -std=c++11 -fexceptions
// QMakeProject: -pipe -Whello -g -std=gnu++11 -Wall -W -D_REENTRANT -fPIC
void CompilerOptionsBuilder::evaluateCompilerFlags()
{
const Core::Id &toolChain = m_projectPart.toolchainType;
if (toolChain == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID
|| toolChain == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) {
m_compilerFlags.forward = true;
for (const QString &option : m_projectPart.compilerFlags) {
// Ignore warning flags as these interfere with ouser user-configured diagnostics.
// Note that once "-w" is provided, no warnings will be emitted, even if "-Wall" follows.
if (option.startsWith("-w", Qt::CaseInsensitive) // -w, -W...
|| option.startsWith("-pedantic")) {
continue;
}
// Check whether a language version is already used.
// Modify if needed as clang accepts c18/gnu18, but not c17/gnu17.
QString theOption = option;
if (theOption.startsWith("-std=")) {
m_compilerFlags.isLanguageVersionSpecified = true;
theOption.replace("=c18", "=c17");
theOption.replace("=gnu18", "=gnu17");
}
m_compilerFlags.flags.append(theOption);
}
}
}
} // namespace CppTools } // namespace CppTools

View File

@@ -61,6 +61,7 @@ public:
void addTargetTriple(); void addTargetTriple();
void addExtraCodeModelFlags(); void addExtraCodeModelFlags();
void addCompilerFlags();
void insertWrappedQtHeaders(); void insertWrappedQtHeaders();
void addLanguageVersionAndExtensions(); void addLanguageVersionAndExtensions();
void updateFileLanguage(ProjectFile::Kind fileKind); void updateFileLanguage(ProjectFile::Kind fileKind);
@@ -80,10 +81,12 @@ public:
void reset(); void reset();
private: private:
void evaluateCompilerFlags();
bool excludeDefineDirective(const ProjectExplorer::Macro &macro) const; bool excludeDefineDirective(const ProjectExplorer::Macro &macro) const;
QString includeDirOptionForPath(const QString &path) const; QString includeDirOptionForPath(const QString &path) const;
void addWrappedQtHeadersIncludePath(QStringList &list) const; void addWrappedQtHeadersIncludePath(QStringList &list) const;
QString includeDirOptionForSystemPath(ProjectExplorer::HeaderPathType type) const; QString includeDirOptionForSystemPath(ProjectExplorer::HeaderPathType type) const;
QByteArray msvcVersion() const;
private: private:
const ProjectPart &m_projectPart; const ProjectPart &m_projectPart;
@@ -96,7 +99,11 @@ private:
const QString m_clangVersion; const QString m_clangVersion;
const QString m_clangResourceDirectory; const QString m_clangResourceDirectory;
QByteArray msvcVersion() const; struct {
bool forward = false;
QStringList flags;
bool isLanguageVersionSpecified = false;
} m_compilerFlags;
QStringList m_options; QStringList m_options;
}; };

View File

@@ -505,6 +505,7 @@ void Dumper::dumpProjectInfos( const QList<ProjectInfo> &projectInfos)
m_out << i3 << "Project Part Name : " << part->displayName << "\n"; m_out << i3 << "Project Part Name : " << part->displayName << "\n";
m_out << i3 << "Project Name : " << projectName << "\n"; m_out << i3 << "Project Name : " << projectName << "\n";
m_out << i3 << "Project File : " << projectFilePath << "\n"; m_out << i3 << "Project File : " << projectFilePath << "\n";
m_out << i3 << "Compiler Flags : " << part->compilerFlags.join(", ") << "\n";
m_out << i3 << "Selected For Building: " << part->selectedForBuilding << "\n"; m_out << i3 << "Selected For Building: " << part->selectedForBuilding << "\n";
m_out << i3 << "Build Target Type : " << Utils::toString(part->buildTargetType) << "\n"; m_out << i3 << "Build Target Type : " << Utils::toString(part->buildTargetType) << "\n";
m_out << i3 << "Lanugage Version : " << Utils::toString(part->languageVersion)<<"\n"; m_out << i3 << "Lanugage Version : " << Utils::toString(part->languageVersion)<<"\n";

View File

@@ -162,6 +162,7 @@ ProjectPart::Ptr ProjectInfoGenerator::createProjectPart(
: ProjectPart::WordWidth32Bit; : ProjectPart::WordWidth32Bit;
part->toolChainTargetTriple = tcInfo.targetTriple; part->toolChainTargetTriple = tcInfo.targetTriple;
part->extraCodeModelFlags = tcInfo.extraCodeModelFlags; part->extraCodeModelFlags = tcInfo.extraCodeModelFlags;
part->compilerFlags = flags.commandLineFlags;
part->warningFlags = flags.warningFlags; part->warningFlags = flags.warningFlags;
part->languageExtensions = flags.languageExtensions; part->languageExtensions = flags.languageExtensions;

View File

@@ -36,8 +36,8 @@ RawProjectPartFlags::RawProjectPartFlags(const ProjectExplorer::ToolChain *toolC
{ {
// Keep the following cheap/non-blocking for the ui thread. Expensive // Keep the following cheap/non-blocking for the ui thread. Expensive
// operations are encapsulated in ToolChainInfo as "runners". // operations are encapsulated in ToolChainInfo as "runners".
this->commandLineFlags = commandLineFlags;
if (toolChain) { if (toolChain) {
this->commandLineFlags = commandLineFlags;
warningFlags = toolChain->warningFlags(commandLineFlags); warningFlags = toolChain->warningFlags(commandLineFlags);
languageExtensions = toolChain->languageExtensions(commandLineFlags); languageExtensions = toolChain->languageExtensions(commandLineFlags);
} }

View File

@@ -120,6 +120,7 @@ public:
// Misc // Misc
QStringList extraCodeModelFlags; QStringList extraCodeModelFlags;
QStringList compilerFlags;
}; };
} // namespace CppTools } // namespace CppTools

View File

@@ -85,6 +85,72 @@ TEST_F(CompilerOptionsBuilder, AddToolchainAndProjectMacros)
ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-Dfoo=bar", "-DprojectFoo=projectBar")); ASSERT_THAT(compilerOptionsBuilder.options(), ElementsAre("-Dfoo=bar", "-DprojectFoo=projectBar"));
} }
TEST_F(CompilerOptionsBuilder, CompilerFlagsFiltering_UnknownOptionsAreForwarded)
{
ProjectPart part = projectPart;
part.compilerFlags = QStringList{"-fancyFlag"};
CppTools::CompilerOptionsBuilder compilerOptionsBuilder{part,
CppTools::UseSystemHeader::No,
CppTools::UseToolchainMacros::Yes,
CppTools::UseTweakedHeaderPaths::Yes,
CppTools::UseLanguageDefines::Yes};
compilerOptionsBuilder.build(ProjectFile::CXXSource, CppTools::UsePrecompiledHeaders::No);
ASSERT_THAT(compilerOptionsBuilder.options(), Contains(part.compilerFlags.first()));
}
TEST_F(CompilerOptionsBuilder, CompilerFlagsFiltering_DiagnosticOptionsAreRemoved)
{
ProjectPart part = projectPart;
part.compilerFlags = QStringList{"-Wbla", "-pedantic"};
CppTools::CompilerOptionsBuilder compilerOptionsBuilder{part,
CppTools::UseSystemHeader::No,
CppTools::UseToolchainMacros::Yes,
CppTools::UseTweakedHeaderPaths::Yes,
CppTools::UseLanguageDefines::Yes};
compilerOptionsBuilder.build(ProjectFile::CXXSource, CppTools::UsePrecompiledHeaders::No);
ASSERT_THAT(compilerOptionsBuilder.options(), Not(Contains(part.compilerFlags[0])));
ASSERT_THAT(compilerOptionsBuilder.options(), Not(Contains(part.compilerFlags[1])));
}
TEST_F(CompilerOptionsBuilder, CompilerFlagsFiltering_CLanguageVersionIsRewritten)
{
ProjectPart part = projectPart;
part.compilerFlags = QStringList{"-std=c18"};
// We need to set the language version here to overcome a QTC_ASSERT checking
// consistency between ProjectFile::Kind and ProjectPart::LanguageVersion
part.languageVersion = Utils::LanguageVersion::C18;
CppTools::CompilerOptionsBuilder compilerOptionsBuilder{part,
CppTools::UseSystemHeader::No,
CppTools::UseToolchainMacros::Yes,
CppTools::UseTweakedHeaderPaths::Yes,
CppTools::UseLanguageDefines::Yes};
compilerOptionsBuilder.build(ProjectFile::CSource, CppTools::UsePrecompiledHeaders::No);
ASSERT_THAT(compilerOptionsBuilder.options(), Not(Contains(part.compilerFlags.first())));
ASSERT_THAT(compilerOptionsBuilder.options(), Contains("-std=c17"));
}
TEST_F(CompilerOptionsBuilder, CompilerFlagsFiltering_LanguageVersionIsExplicitlySetIfNotProvided)
{
CppTools::CompilerOptionsBuilder compilerOptionsBuilder{projectPart,
CppTools::UseSystemHeader::No,
CppTools::UseToolchainMacros::Yes,
CppTools::UseTweakedHeaderPaths::Yes,
CppTools::UseLanguageDefines::Yes};
compilerOptionsBuilder.build(ProjectFile::CXXSource, CppTools::UsePrecompiledHeaders::No);
ASSERT_THAT(compilerOptionsBuilder.options(), Contains("-std=c++17"));
}
TEST_F(CompilerOptionsBuilder, AddToolchainAndProjectMacrosWithoutSkipingLanguageDefines) TEST_F(CompilerOptionsBuilder, AddToolchainAndProjectMacrosWithoutSkipingLanguageDefines)
{ {
CppTools::CompilerOptionsBuilder compilerOptionsBuilder{projectPart, CppTools::CompilerOptionsBuilder compilerOptionsBuilder{projectPart,
@@ -441,7 +507,7 @@ TEST_F(CompilerOptionsBuilder, BuildAllOptions)
ASSERT_THAT(compilerOptionsBuilder.options(), ASSERT_THAT(compilerOptionsBuilder.options(),
ElementsAre( ElementsAre(
"-nostdlibinc", "-c", "-m64", "-target", "x86_64-apple-darwin10", "-nostdlibinc", "-c", "-m64", "-target", "x86_64-apple-darwin10",
"-arch", "x86_64", "-x", "c++", "-std=c++17", "-Dfoo=bar", "-x", "c++", "-std=c++17", "-arch", "x86_64", "-Dfoo=bar",
"-DprojectFoo=projectBar", "-undef", "-DprojectFoo=projectBar", "-undef",
"-I", IsPartOfHeader("wrappedQtHeaders"), "-I", IsPartOfHeader("wrappedQtHeaders"),
"-I", IsPartOfHeader(QDir::toNativeSeparators("wrappedQtHeaders/QtCore").toStdString()), "-I", IsPartOfHeader(QDir::toNativeSeparators("wrappedQtHeaders/QtCore").toStdString()),