Commit 78db7d7e authored by Ivan Donchevskii's avatar Ivan Donchevskii

Clang: turn off delayed template parsing

Fix templates highlight and completion on Windows
Add UI to turn on/off delayed parsing (off by default)

Task-number: QTCREATORBUG-17222
Change-Id: I0cd5e0bcfff2789cd938e4096829f777ff15957a
Reviewed-by: Nikolai Kosjar's avatarNikolai Kosjar <nikolai.kosjar@qt.io>
parent 0784dd20
...@@ -419,16 +419,24 @@ static QStringList warningOptions(CppTools::ProjectPart *projectPart) ...@@ -419,16 +419,24 @@ static QStringList warningOptions(CppTools::ProjectPart *projectPart)
{ {
if (projectPart && projectPart->project) { if (projectPart && projectPart->project) {
ClangProjectSettings projectSettings(projectPart->project); ClangProjectSettings projectSettings(projectPart->project);
if (!projectSettings.useGlobalWarningConfig()) { if (!projectSettings.useGlobalConfig()) {
const Core::Id warningConfigId = projectSettings.warningConfigId(); const Core::Id warningConfigId = projectSettings.warningConfigId();
const CppTools::ClangDiagnosticConfigsModel configsModel( const CppTools::ClangDiagnosticConfigsModel configsModel(
CppTools::codeModelSettings()->clangCustomDiagnosticConfigs()); CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
if (configsModel.hasConfigWithId(warningConfigId)) if (configsModel.hasConfigWithId(warningConfigId))
return configsModel.configWithId(warningConfigId).commandLineOptions(); return configsModel.configWithId(warningConfigId).commandLineWarnings();
} }
} }
return CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineOptions(); return CppTools::codeModelSettings()->clangDiagnosticConfig().commandLineWarnings();
}
static QStringList commandLineOptions(CppTools::ProjectPart *projectPart)
{
if (!projectPart || !projectPart->project)
return ClangProjectSettings::globalCommandLineOptions();
return ClangProjectSettings{projectPart->project}.commandLineOptions();
} }
static QStringList precompiledHeaderOptions( static QStringList precompiledHeaderOptions(
...@@ -454,6 +462,7 @@ static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart ...@@ -454,6 +462,7 @@ static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart
{ {
return languageOptions(filePath, projectPart) return languageOptions(filePath, projectPart)
+ warningOptions(projectPart) + warningOptions(projectPart)
+ commandLineOptions(projectPart)
+ precompiledHeaderOptions(filePath, projectPart); + precompiledHeaderOptions(filePath, projectPart);
} }
......
...@@ -25,15 +25,23 @@ ...@@ -25,15 +25,23 @@
#include "clangprojectsettings.h" #include "clangprojectsettings.h"
#include <utils/qtcassert.h>
#include <utils/hostosinfo.h>
#include <QDebug>
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
static QString useGlobalWarningConfigKey() static QString useGlobalConfigKey()
{ return QStringLiteral("ClangCodeModel.UseGlobalWarningConfig"); } { return QStringLiteral("ClangCodeModel.UseGlobalConfig"); }
static QString warningConfigIdKey() static QString warningConfigIdKey()
{ return QStringLiteral("ClangCodeModel.WarningConfigId"); } { return QStringLiteral("ClangCodeModel.WarningConfigId"); }
static QString customCommandLineKey()
{ return QLatin1String("ClangCodeModel.CustomCommandLineKey"); }
ClangProjectSettings::ClangProjectSettings(ProjectExplorer::Project *project) ClangProjectSettings::ClangProjectSettings(ProjectExplorer::Project *project)
: m_project(project) : m_project(project)
{ {
...@@ -55,31 +63,55 @@ void ClangProjectSettings::setWarningConfigId(const Core::Id &customConfigId) ...@@ -55,31 +63,55 @@ void ClangProjectSettings::setWarningConfigId(const Core::Id &customConfigId)
m_warningConfigId = customConfigId; m_warningConfigId = customConfigId;
} }
bool ClangProjectSettings::useGlobalWarningConfig() const bool ClangProjectSettings::useGlobalConfig() const
{
return m_useGlobalConfig;
}
void ClangProjectSettings::setUseGlobalConfig(bool useGlobalConfig)
{ {
return m_useGlobalWarningConfig; m_useGlobalConfig = useGlobalConfig;
} }
void ClangProjectSettings::setUseGlobalWarningConfig(bool useGlobalWarningConfig) QStringList ClangProjectSettings::commandLineOptions() const
{ {
m_useGlobalWarningConfig = useGlobalWarningConfig; return m_useGlobalConfig ? globalCommandLineOptions()
: m_customCommandLineOptions;
}
void ClangProjectSettings::setCommandLineOptions(const QStringList &options)
{
QTC_ASSERT(!m_useGlobalConfig, qDebug()
<< "setCommandLineOptions was called while using global project config");
m_customCommandLineOptions = options;
} }
void ClangProjectSettings::load() void ClangProjectSettings::load()
{ {
const QVariant useGlobalConfigVariant = m_project->namedSettings(useGlobalWarningConfigKey()); const QVariant useGlobalConfigVariant = m_project->namedSettings(useGlobalConfigKey());
const bool useGlobalConfig = useGlobalConfigVariant.isValid() const bool useGlobalConfig = useGlobalConfigVariant.isValid()
? useGlobalConfigVariant.toBool() ? useGlobalConfigVariant.toBool()
: true; : true;
setUseGlobalWarningConfig(useGlobalConfig); setUseGlobalConfig(useGlobalConfig);
setWarningConfigId(Core::Id::fromSetting(m_project->namedSettings(warningConfigIdKey()))); setWarningConfigId(Core::Id::fromSetting(m_project->namedSettings(warningConfigIdKey())));
m_customCommandLineOptions = m_project->namedSettings(customCommandLineKey()).toStringList();
if (m_customCommandLineOptions.empty())
m_customCommandLineOptions = globalCommandLineOptions();
} }
void ClangProjectSettings::store() void ClangProjectSettings::store()
{ {
m_project->setNamedSettings(useGlobalWarningConfigKey(), useGlobalWarningConfig()); m_project->setNamedSettings(useGlobalConfigKey(), useGlobalConfig());
m_project->setNamedSettings(warningConfigIdKey(), warningConfigId().toSetting()); m_project->setNamedSettings(warningConfigIdKey(), warningConfigId().toSetting());
m_project->setNamedSettings(customCommandLineKey(), m_customCommandLineOptions);
}
QStringList ClangProjectSettings::globalCommandLineOptions()
{
if (Utils::HostOsInfo::isWindowsHost())
return {QLatin1String{GlobalWindowsCmdOptions}};
return {};
} }
} // namespace Internal } // namespace Internal
......
...@@ -39,21 +39,32 @@ class ClangProjectSettings: public QObject ...@@ -39,21 +39,32 @@ class ClangProjectSettings: public QObject
Q_OBJECT Q_OBJECT
public: public:
constexpr static const char* DelayedTemplateParsing = "-fdelayed-template-parsing";
constexpr static const char* NoDelayedTemplateParsing = "-fno-delayed-template-parsing";
constexpr static const char* GlobalWindowsCmdOptions = NoDelayedTemplateParsing;
ClangProjectSettings(ProjectExplorer::Project *project); ClangProjectSettings(ProjectExplorer::Project *project);
bool useGlobalWarningConfig() const; bool useGlobalConfig() const;
void setUseGlobalWarningConfig(bool useGlobalWarningConfig); void setUseGlobalConfig(bool useGlobalConfig);
Core::Id warningConfigId() const; Core::Id warningConfigId() const;
void setWarningConfigId(const Core::Id &warningConfigId); void setWarningConfigId(const Core::Id &warningConfigId);
QStringList commandLineOptions() const;
void setCommandLineOptions(const QStringList &options);
void load(); void load();
void store(); void store();
static QStringList globalCommandLineOptions();
private: private:
ProjectExplorer::Project *m_project; ProjectExplorer::Project *m_project;
bool m_useGlobalWarningConfig = true; bool m_useGlobalConfig = true;
Core::Id m_warningConfigId; Core::Id m_warningConfigId;
QStringList m_customCommandLineOptions;
}; };
} // namespace Internal } // namespace Internal
......
...@@ -34,60 +34,21 @@ ...@@ -34,60 +34,21 @@
#include <cpptools/cppcodemodelsettings.h> #include <cpptools/cppcodemodelsettings.h>
#include <cpptools/cpptoolsreuse.h> #include <cpptools/cpptoolsreuse.h>
static const char GLOBAL_PROXY_CONFIG_ID[] = "globalProxyConfig"; #include <utils/hostosinfo.h>
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
static CppTools::ClangDiagnosticConfig static Core::Id configIdForProject(ClangProjectSettings &projectSettings)
createConfigRepresentingGlobalSetting(const CppTools::ClangDiagnosticConfig &baseConfig)
{ {
CppTools::ClangDiagnosticConfig config = baseConfig; if (projectSettings.useGlobalConfig())
config.setId(GLOBAL_PROXY_CONFIG_ID); return CppTools::codeModelSettings()->clangDiagnosticConfigId();
Core::Id configId = projectSettings.warningConfigId();
QString displayName = config.displayName(); if (!configId.isValid()) {
if (config.isReadOnly()) configId = CppTools::codeModelSettings()->clangDiagnosticConfigId();
displayName = CppTools::ClangDiagnosticConfigsModel::displayNameWithBuiltinIndication(config); projectSettings.setWarningConfigId(configId);
displayName = ClangProjectSettingsWidget::tr("Global setting (%1)").arg(displayName); }
return configId;
config.setDisplayName(displayName);
config.setIsReadOnly(true);
return config;
}
static Core::Id globalConfigId(const CppTools::CppCodeModelSettings &settings,
const CppTools::ClangDiagnosticConfigsModel &model)
{
const Core::Id configId = settings.clangDiagnosticConfigId();
if (model.hasConfigWithId(configId))
return configId;
return model.at(0).id(); // Config saved in the settings was removed, fallback to first.
}
static CppTools::ClangDiagnosticConfigsModel
createConfigsModelWithGlobalProxyConfig(const CppTools::CppCodeModelSettings &settings)
{
using namespace CppTools;
ClangDiagnosticConfigsModel configsModel(settings.clangCustomDiagnosticConfigs());
const Core::Id globalId = globalConfigId(settings, configsModel);
const ClangDiagnosticConfig globalConfig = configsModel.configWithId(globalId);
const ClangDiagnosticConfig globalProxy
= createConfigRepresentingGlobalSetting(globalConfig);
configsModel.prepend(globalProxy);
return configsModel;
}
static Core::Id configIdForProject(const ClangProjectSettings &projectSettings)
{
return projectSettings.useGlobalWarningConfig()
? Core::Id(GLOBAL_PROXY_CONFIG_ID)
: projectSettings.warningConfigId();
} }
ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project *project) ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project *project)
...@@ -98,24 +59,33 @@ ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project ...@@ -98,24 +59,33 @@ ClangProjectSettingsWidget::ClangProjectSettingsWidget(ProjectExplorer::Project
using namespace CppTools; using namespace CppTools;
m_diagnosticConfigWidget = new ClangDiagnosticConfigsWidget; m_diagnosticConfigWidget = new ClangDiagnosticConfigsWidget;
m_diagnosticConfigWidget->setConfigWithUndecoratedDisplayName(Core::Id(GLOBAL_PROXY_CONFIG_ID));
refreshDiagnosticConfigsWidgetFromSettings(); refreshDiagnosticConfigsWidgetFromSettings();
m_ui.generalConfigurationGroupBox->setVisible(Utils::HostOsInfo::isWindowsHost());
m_ui.clangSettings->setCurrentIndex(m_projectSettings.useGlobalConfig() ? 0 : 1);
syncOtherWidgetsToComboBox();
connectToCppCodeModelSettingsChanged(); connectToCppCodeModelSettingsChanged();
connect(m_diagnosticConfigWidget.data(), &ClangDiagnosticConfigsWidget::currentConfigChanged, connect(m_diagnosticConfigWidget.data(), &ClangDiagnosticConfigsWidget::currentConfigChanged,
this, &ClangProjectSettingsWidget::onCurrentWarningConfigChanged); this, &ClangProjectSettingsWidget::onCurrentWarningConfigChanged);
connect(m_diagnosticConfigWidget.data(), &ClangDiagnosticConfigsWidget::customConfigsChanged, connect(m_diagnosticConfigWidget.data(), &ClangDiagnosticConfigsWidget::customConfigsChanged,
this, &ClangProjectSettingsWidget::onCustomWarningConfigsChanged); this, &ClangProjectSettingsWidget::onCustomWarningConfigsChanged);
connect(m_ui.delayedTemplateParse, &QCheckBox::toggled,
this, &ClangProjectSettingsWidget::onDelayedTemplateParseClicked);
connect(m_ui.clangSettings,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, &ClangProjectSettingsWidget::onClangSettingsChanged);
m_ui.diagnosticConfigurationGroupBox->layout()->addWidget(m_diagnosticConfigWidget); m_ui.diagnosticConfigurationGroupBox->layout()->addWidget(m_diagnosticConfigWidget);
} }
void ClangProjectSettingsWidget::onCurrentWarningConfigChanged(const Core::Id &currentConfigId) void ClangProjectSettingsWidget::onCurrentWarningConfigChanged(const Core::Id &currentConfigId)
{ {
const bool useGlobalConfig = currentConfigId == Core::Id(GLOBAL_PROXY_CONFIG_ID); // Don't save it when we reset the global config in code
if (m_projectSettings.useGlobalConfig())
m_projectSettings.setUseGlobalWarningConfig(useGlobalConfig); return;
m_projectSettings.setWarningConfigId(currentConfigId); m_projectSettings.setWarningConfigId(currentConfigId);
m_projectSettings.store(); m_projectSettings.store();
} }
...@@ -132,11 +102,48 @@ void ClangProjectSettingsWidget::onCustomWarningConfigsChanged( ...@@ -132,11 +102,48 @@ void ClangProjectSettingsWidget::onCustomWarningConfigsChanged(
connectToCppCodeModelSettingsChanged(); connectToCppCodeModelSettingsChanged();
} }
void ClangProjectSettingsWidget::onDelayedTemplateParseClicked(bool checked)
{
// Don't save it when we reset the global config in code
if (m_projectSettings.useGlobalConfig())
return;
const QLatin1String extraFlag{checked ? ClangProjectSettings::DelayedTemplateParsing
: ClangProjectSettings::NoDelayedTemplateParsing};
QStringList options = m_projectSettings.commandLineOptions();
options.removeAll(QLatin1String{ClangProjectSettings::DelayedTemplateParsing});
options.removeAll(QLatin1String{ClangProjectSettings::NoDelayedTemplateParsing});
options.append(extraFlag);
m_projectSettings.setCommandLineOptions(options);
m_projectSettings.store();
}
void ClangProjectSettingsWidget::onClangSettingsChanged(int index)
{
m_projectSettings.setUseGlobalConfig(index == 0 ? true : false);
m_projectSettings.store();
syncOtherWidgetsToComboBox();
}
void ClangProjectSettingsWidget::syncOtherWidgetsToComboBox()
{
const QStringList options = m_projectSettings.commandLineOptions();
m_ui.delayedTemplateParse->setChecked(
options.contains(QLatin1String{ClangProjectSettings::DelayedTemplateParsing}));
const bool isCustom = !m_projectSettings.useGlobalConfig();
m_ui.generalConfigurationGroupBox->setEnabled(isCustom);
m_ui.diagnosticConfigurationGroupBox->setEnabled(isCustom);
refreshDiagnosticConfigsWidgetFromSettings();
}
void ClangProjectSettingsWidget::refreshDiagnosticConfigsWidgetFromSettings() void ClangProjectSettingsWidget::refreshDiagnosticConfigsWidgetFromSettings()
{ {
m_diagnosticConfigWidget->refresh( CppTools::ClangDiagnosticConfigsModel configsModel(
createConfigsModelWithGlobalProxyConfig(*CppTools::codeModelSettings()), CppTools::codeModelSettings()->clangCustomDiagnosticConfigs());
configIdForProject(m_projectSettings)); m_diagnosticConfigWidget->refresh(configsModel,
configIdForProject(m_projectSettings));
} }
void ClangProjectSettingsWidget::connectToCppCodeModelSettingsChanged() void ClangProjectSettingsWidget::connectToCppCodeModelSettingsChanged()
......
...@@ -49,9 +49,12 @@ public: ...@@ -49,9 +49,12 @@ public:
private: private:
void onCurrentWarningConfigChanged(const Core::Id &currentConfigId); void onCurrentWarningConfigChanged(const Core::Id &currentConfigId);
void onCustomWarningConfigsChanged(const CppTools::ClangDiagnosticConfigs &customConfigs); void onCustomWarningConfigsChanged(const CppTools::ClangDiagnosticConfigs &customConfigs);
void onDelayedTemplateParseClicked(bool);
void onClangSettingsChanged(int index);
void refreshDiagnosticConfigsWidgetFromSettings(); void refreshDiagnosticConfigsWidgetFromSettings();
void connectToCppCodeModelSettingsChanged(); void connectToCppCodeModelSettingsChanged();
void disconnectFromCppCodeModelSettingsChanged(); void disconnectFromCppCodeModelSettingsChanged();
void syncOtherWidgetsToComboBox();
private: private:
Ui::ClangProjectSettingsWidget m_ui; Ui::ClangProjectSettingsWidget m_ui;
......
...@@ -14,6 +14,52 @@ ...@@ -14,6 +14,52 @@
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QComboBox" name="clangSettings">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Global</string>
</property>
</item>
<item>
<property name="text">
<string>Custom</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QGroupBox" name="generalConfigurationGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>General</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="delayedTemplateParse">
<property name="toolTip">
<string>Parse templates in a MSVC-compliant way. This helps to parse headers for example from Active Template Library (ATL) or Windows Runtime Library (WRL).
However, using the relaxed and extended rules means also that no highlighting/completion can be provided within template functions.</string>
</property>
<property name="text">
<string>Enable MSVC-compliant template parsing</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="diagnosticConfigurationGroupBox"> <widget class="QGroupBox" name="diagnosticConfigurationGroupBox">
<property name="title"> <property name="title">
......
...@@ -47,14 +47,14 @@ void ClangDiagnosticConfig::setDisplayName(const QString &displayName) ...@@ -47,14 +47,14 @@ void ClangDiagnosticConfig::setDisplayName(const QString &displayName)
m_displayName = displayName; m_displayName = displayName;
} }
QStringList ClangDiagnosticConfig::commandLineOptions() const QStringList ClangDiagnosticConfig::commandLineWarnings() const
{ {
return m_commandLineOptions; return m_commandLineWarnings;
} }
void ClangDiagnosticConfig::setCommandLineOptions(const QStringList &options) void ClangDiagnosticConfig::setCommandLineWarnings(const QStringList &warnings)
{ {
m_commandLineOptions = options; m_commandLineWarnings = warnings;
} }
bool ClangDiagnosticConfig::isReadOnly() const bool ClangDiagnosticConfig::isReadOnly() const
...@@ -71,7 +71,7 @@ bool ClangDiagnosticConfig::operator==(const ClangDiagnosticConfig &other) const ...@@ -71,7 +71,7 @@ bool ClangDiagnosticConfig::operator==(const ClangDiagnosticConfig &other) const
{ {
return m_id == other.m_id return m_id == other.m_id
&& m_displayName == other.m_displayName && m_displayName == other.m_displayName
&& m_commandLineOptions == other.m_commandLineOptions && m_commandLineWarnings == other.m_commandLineWarnings
&& m_isReadOnly == other.m_isReadOnly; && m_isReadOnly == other.m_isReadOnly;
} }
......
...@@ -43,8 +43,8 @@ public: ...@@ -43,8 +43,8 @@ public:
QString displayName() const; QString displayName() const;
void setDisplayName(const QString &displayName); void setDisplayName(const QString &displayName);
QStringList commandLineOptions() const; QStringList commandLineWarnings() const;
void setCommandLineOptions(const QStringList &commandLineOptions); void setCommandLineWarnings(const QStringList &commandLineWarnings);
bool isReadOnly() const; bool isReadOnly() const;
void setIsReadOnly(bool isReadOnly); void setIsReadOnly(bool isReadOnly);
...@@ -54,7 +54,7 @@ public: ...@@ -54,7 +54,7 @@ public:
private: private:
Core::Id m_id; Core::Id m_id;
QString m_displayName; QString m_displayName;
QStringList m_commandLineOptions; QStringList m_commandLineWarnings;
bool m_isReadOnly = false; bool m_isReadOnly = false;
}; };
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
namespace CppTools { namespace CppTools {
static QStringList commonOptions() static QStringList commonWarnings()
{ {
return { QStringLiteral("-Wno-unknown-pragmas") }; return { QStringLiteral("-Wno-unknown-pragmas") };
} }
...@@ -45,10 +45,10 @@ static void addConfigForQuestionableConstructs(ClangDiagnosticConfigsModel &mode ...@@ -45,10 +45,10 @@ static void addConfigForQuestionableConstructs(ClangDiagnosticConfigsModel &mode
config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel", config.setDisplayName(QCoreApplication::translate("ClangDiagnosticConfigsModel",
"Warnings for questionable constructs")); "Warnings for questionable constructs"));
config.setIsReadOnly(true); config.setIsReadOnly(true);
config.setCommandLineOptions(QStringList{ config.setCommandLineWarnings(QStringList{
QStringLiteral("-Wall"), QStringLiteral("-Wall"),
QStringLiteral("-Wextra"), QStringLiteral("-Wextra"),
} + commonOptions()); } + commonWarnings());
model.appendOrUpdate(config); model.appendOrUpdate(config);