From d8f119c8a222188556bf63e7adbef24c9ca3fe7f Mon Sep 17 00:00:00 2001
From: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
Date: Tue, 10 Nov 2015 16:54:53 +0100
Subject: [PATCH] Clang: Allow to provide extra command line options

This can be used to experiment with clang options that e.g. affect
diagnostics.

Changes take effect on editor re-open.

Change-Id: Ie46d0ff085a3700a748dbcf4b94b93b0bf9c4642
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@theqtcompany.com>
Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com>
---
 doc/src/editors/creator-clang-codemodel.qdoc  |  2 +-
 .../clangeditordocumentprocessor.cpp          | 13 ++++-
 src/plugins/clangcodemodel/clangutils.cpp     | 27 +--------
 src/plugins/cpptools/cppcodemodelsettings.cpp | 31 ++++++++++
 src/plugins/cpptools/cppcodemodelsettings.h   |  5 ++
 .../cpptools/cppcodemodelsettingspage.cpp     | 20 +++++--
 .../cpptools/cppcodemodelsettingspage.ui      | 57 ++++++++++++++-----
 src/plugins/cpptools/cpptoolsconstants.h      |  1 +
 8 files changed, 107 insertions(+), 49 deletions(-)

diff --git a/doc/src/editors/creator-clang-codemodel.qdoc b/doc/src/editors/creator-clang-codemodel.qdoc
index fedc299804..94d2bd4de9 100644
--- a/doc/src/editors/creator-clang-codemodel.qdoc
+++ b/doc/src/editors/creator-clang-codemodel.qdoc
@@ -142,7 +142,7 @@
 
         \li Select \uicontrol Tools > \uicontrol Options >
             \uicontrol {C++} > \uicontrol {Code Model},
-            and select the parser to use for files of each type.
+            and select \uicontrol {Use Clang Code Model}.
 
         \li To process pre-compiled headers before processing any project files,
             deselect the \uicontrol {Ignore pre-compiled headers} check box.
diff --git a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
index aa4bee6896..341f541255 100644
--- a/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
+++ b/src/plugins/clangcodemodel/clangeditordocumentprocessor.cpp
@@ -41,8 +41,9 @@
 #include <diagnosticcontainer.h>
 #include <sourcelocationcontainer.h>
 
+#include <cpptools/cppcodemodelsettings.h>
 #include <cpptools/cppprojects.h>
-#include <cpptools/cpptoolsplugin.h>
+#include <cpptools/cpptoolsreuse.h>
 #include <cpptools/cppworkingcopy.h>
 
 #include <texteditor/convenience.h>
@@ -319,15 +320,21 @@ static QStringList languageOptions(const QString &filePath, CppTools::ProjectPar
     return builder.options();
 }
 
+static QStringList fileArguments(const QString &filePath, CppTools::ProjectPart *projectPart)
+{
+    return QStringList(languageOptions(filePath, projectPart))
+         + CppTools::codeModelSettings()->extraClangOptions();
+}
+
 ClangBackEnd::FileContainer
 ClangEditorDocumentProcessor::fileContainer(CppTools::ProjectPart *projectPart) const
 {
     const auto projectPartId = projectPart
             ? Utf8String::fromString(projectPart->id())
             : Utf8String();
-    const auto theLanguageOption = languageOptions(filePath(), projectPart);
+    const QStringList theFileArguments = fileArguments(filePath(), projectPart);
 
-    return {filePath(), projectPartId, Utf8StringVector(theLanguageOption), revision()};
+    return {filePath(), projectPartId, Utf8StringVector(theFileArguments), revision()};
 }
 
 } // namespace Internal
diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp
index 2fe9d97b60..fd9064a3f5 100644
--- a/src/plugins/clangcodemodel/clangutils.cpp
+++ b/src/plugins/clangcodemodel/clangutils.cpp
@@ -127,8 +127,6 @@ public:
         optionsBuilder.addHeaderPathOptions();
         optionsBuilder.addProjectConfigFileInclude();
 
-        optionsBuilder.addDiagnosticOptions();
-
         optionsBuilder.addExtraOptions();
 
         return optionsBuilder.options();
@@ -191,30 +189,7 @@ private:
         add(QLatin1String("-fdiagnostics-show-note-include-stack"));
         add(QLatin1String("-fmacro-backtrace-limit=0"));
         add(QLatin1String("-fretain-comments-from-system-headers"));
-        // TODO: -Xclang -ferror-limit -Xclang 0 ?
-    }
-
-    void addDiagnosticOptions()
-    {
-        add(QStringLiteral("-fmessage-length=0"));
-        add(QStringLiteral("-fdiagnostics-show-note-include-stack"));
-        add(QStringLiteral("-fmacro-backtrace-limit=0"));
-        add(QStringLiteral("-fretain-comments-from-system-headers"));
-        add(QStringLiteral("-ferror-limit=1000"));
-
-        add(QStringLiteral("-Weverything"));
-        add(QStringLiteral("-Wno-c++98-compat"));
-        add(QStringLiteral("-Wno-c++98-compat-pedantic"));
-        add(QStringLiteral("-Wno-unused-macros"));
-        add(QStringLiteral("-Wno-newline-eof"));
-        add(QStringLiteral("-Wno-exit-time-destructors"));
-        add(QStringLiteral("-Wno-global-constructors"));
-        add(QStringLiteral("-Wno-gnu-zero-variadic-macro-arguments"));
-        add(QStringLiteral("-Wno-documentation"));
-        add(QStringLiteral("-Wno-shadow"));
-
-        if (m_projectPart.languageVersion >= ProjectPart::CXX98)
-            add(QStringLiteral("-Wno-missing-prototypes"));
+        add(QLatin1String("-ferror-limit=1000"));
     }
 };
 
diff --git a/src/plugins/cpptools/cppcodemodelsettings.cpp b/src/plugins/cpptools/cppcodemodelsettings.cpp
index 35555868a1..5d35cf7d3e 100644
--- a/src/plugins/cpptools/cppcodemodelsettings.cpp
+++ b/src/plugins/cpptools/cppcodemodelsettings.cpp
@@ -36,6 +36,7 @@ using namespace CppTools;
 
 static QLatin1String cppHeaderMimeType(Constants::CPP_HEADER_MIMETYPE);
 static QLatin1String cHeaderMimeType(Constants::C_HEADER_MIMETYPE);
+static QLatin1String clangExtraOptionsKey(Constants::CPPTOOLS_EXTRA_CLANG_OPTIONS);
 
 void CppCodeModelSettings::fromSettings(QSettings *s)
 {
@@ -45,6 +46,8 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
     foreach (const QString &mimeType, supportedMimeTypes())
         setIdForMimeType(supporters, mimeType);
 
+    setExtraClangOptions(s->value(clangExtraOptionsKey, defaultExtraClangOptions()).toStringList());
+
     QVariant v = s->value(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE), PchUse_None);
     setPCHUsage(static_cast<PCHUsage>(v.toInt()));
     s->endGroup();
@@ -59,6 +62,7 @@ void CppCodeModelSettings::toSettings(QSettings *s)
     foreach (const QString &mimeType, m_modelManagerSupportByMimeType.keys())
         var[mimeType] = m_modelManagerSupportByMimeType[mimeType];
     s->setValue(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_SUPPORTERS_KEY), QVariant(var));
+    s->setValue(clangExtraOptionsKey, extraClangOptions());
     s->setValue(QLatin1String(Constants::CPPTOOLS_MODEL_MANAGER_PCH_USAGE), pchUsage());
     s->endGroup();
 
@@ -116,6 +120,33 @@ bool CppCodeModelSettings::hasModelManagerSupportIdForMimeType(const QString &mi
         return m_modelManagerSupportByMimeType.value(mimeType) == id;
 }
 
+QStringList CppCodeModelSettings::defaultExtraClangOptions()
+{
+    return {
+        QStringLiteral("-Weverything"),
+        QStringLiteral("-Wno-c++98-compat"),
+        QStringLiteral("-Wno-c++98-compat-pedantic"),
+        QStringLiteral("-Wno-unused-macros"),
+        QStringLiteral("-Wno-newline-eof"),
+        QStringLiteral("-Wno-exit-time-destructors"),
+        QStringLiteral("-Wno-global-constructors"),
+        QStringLiteral("-Wno-gnu-zero-variadic-macro-arguments"),
+        QStringLiteral("-Wno-documentation"),
+        QStringLiteral("-Wno-shadow"),
+        QStringLiteral("-Wno-missing-prototypes"), // Not optimal for C projects.
+    };
+}
+
+QStringList CppCodeModelSettings::extraClangOptions() const
+{
+    return m_extraClangOptions;
+}
+
+void CppCodeModelSettings::setExtraClangOptions(const QStringList &extraClangOptions)
+{
+    m_extraClangOptions = extraClangOptions;
+}
+
 void CppCodeModelSettings::setIdForMimeType(const QVariant &var, const QString &mimeType)
 {
     QHash<QString, QVariant> mimeToId = var.toHash();
diff --git a/src/plugins/cpptools/cppcodemodelsettings.h b/src/plugins/cpptools/cppcodemodelsettings.h
index 8c07c1671f..2d14d24bd6 100644
--- a/src/plugins/cpptools/cppcodemodelsettings.h
+++ b/src/plugins/cpptools/cppcodemodelsettings.h
@@ -73,6 +73,10 @@ public:
     void setDefaultId(const QString &defaultId)
     { m_defaultId = defaultId; }
 
+    static QStringList defaultExtraClangOptions();
+    QStringList extraClangOptions() const;
+    void setExtraClangOptions(const QStringList &extraClangOptions);
+
     PCHUsage pchUsage() const { return m_pchUsage; }
     void setPCHUsage(PCHUsage pchUsage) { m_pchUsage = pchUsage; }
 
@@ -90,6 +94,7 @@ private:
 private:
     QHash<QString, QString> m_modelManagerSupportByMimeType;
     QHash<QString, QString> m_modelManagerSupportsByName;
+    QStringList m_extraClangOptions;
     QString m_defaultId;
     PCHUsage m_pchUsage;
 };
diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.cpp b/src/plugins/cpptools/cppcodemodelsettingspage.cpp
index e59e0d1dbb..f3295e776b 100644
--- a/src/plugins/cpptools/cppcodemodelsettingspage.cpp
+++ b/src/plugins/cpptools/cppcodemodelsettingspage.cpp
@@ -46,7 +46,11 @@ CppCodeModelSettingsWidget::CppCodeModelSettingsWidget(QWidget *parent)
 {
     m_ui->setupUi(this);
 
-    m_ui->theGroupBox->setVisible(true);
+    m_ui->clangSettingsGroupBox->setVisible(true);
+    connect(m_ui->clangOptionsResetButton, &QPushButton::clicked, [this]() {
+        const QString options = m_settings->defaultExtraClangOptions().join(QLatin1Char('\n'));
+        m_ui->clangOptionsToAppendTextEdit->document()->setPlainText(options);
+    });
 }
 
 CppCodeModelSettingsWidget::~CppCodeModelSettingsWidget()
@@ -96,8 +100,11 @@ void CppCodeModelSettingsWidget::setupClangCodeModelWidgets() const
         isClangActive = isClangCodeModelActive(*m_settings.data());
 
     m_ui->activateClangCodeModelPluginHint->setVisible(!isClangAvailable);
-    m_ui->useClangCheckBox->setEnabled(isClangAvailable);
-    m_ui->useClangCheckBox->setChecked(isClangActive);
+    m_ui->clangSettingsGroupBox->setEnabled(isClangAvailable);
+    m_ui->clangSettingsGroupBox->setChecked(isClangActive);
+
+    const QString extraClangOptions = m_settings->extraClangOptions().join(QLatin1Char('\n'));
+    m_ui->clangOptionsToAppendTextEdit->document()->setPlainText(extraClangOptions);
 }
 
 bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const
@@ -106,13 +113,18 @@ bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const
     // Until then, ensure that the settings are set uniformly for all the mime types
     // to avoid surprises.
 
-    const QString activeCodeModelId = m_ui->useClangCheckBox->isChecked()
+    const QString activeCodeModelId = m_ui->clangSettingsGroupBox->isChecked()
             ? QLatin1String("ClangCodeMode.ClangCodeMode")
             : QLatin1String("CppTools.BuiltinCodeModel");
 
     foreach (const QString &mimeType, m_settings->supportedMimeTypes())
         m_settings->setModelManagerSupportIdForMimeType(mimeType, activeCodeModelId);
 
+    const QString clangOptionsText = m_ui->clangOptionsToAppendTextEdit->document()->toPlainText();
+    const QStringList extraClangOptions = clangOptionsText.split(QLatin1Char('\n'),
+                                                                 QString::SkipEmptyParts);
+    m_settings->setExtraClangOptions(extraClangOptions);
+
     return true;
 }
 
diff --git a/src/plugins/cpptools/cppcodemodelsettingspage.ui b/src/plugins/cpptools/cppcodemodelsettingspage.ui
index e8146a0fed..de7b381b16 100644
--- a/src/plugins/cpptools/cppcodemodelsettingspage.ui
+++ b/src/plugins/cpptools/cppcodemodelsettingspage.ui
@@ -15,27 +15,54 @@
   </property>
   <layout class="QVBoxLayout" name="verticalLayout_2">
    <item>
-    <widget class="QGroupBox" name="theGroupBox">
+    <widget class="QLabel" name="activateClangCodeModelPluginHint">
+     <property name="text">
+      <string>&lt;i&gt;Activate the Clang Code Model plugin to enable the options here.&lt;/i&gt;</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="clangSettingsGroupBox">
      <property name="title">
-      <string>Code Completion and Semantic Highlighting</string>
+      <string>Use Clang Code Model</string>
+     </property>
+     <property name="checkable">
+      <bool>true</bool>
      </property>
-     <layout class="QFormLayout" name="formLayout">
-      <property name="fieldGrowthPolicy">
-       <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
-      </property>
-      <item row="1" column="0">
-       <widget class="QCheckBox" name="useClangCheckBox">
+     <layout class="QVBoxLayout" name="verticalLayout_3">
+      <item>
+       <widget class="QLabel" name="clangOptionsGeneralHintLabel">
         <property name="text">
-         <string>Use Clang Code Model</string>
+         <string>Append additional command line options to Clang, one per line. &lt;i&gt;Use this with care.&lt;/i&gt;</string>
         </property>
        </widget>
       </item>
-      <item row="0" column="0">
-       <widget class="QLabel" name="activateClangCodeModelPluginHint">
-        <property name="text">
-         <string>&lt;i&gt;Activate the Clang Code Model plugin to enable the options here.&lt;/i&gt;</string>
-        </property>
-       </widget>
+      <item>
+       <widget class="QPlainTextEdit" name="clangOptionsToAppendTextEdit"/>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QPushButton" name="clangOptionsResetButton">
+          <property name="text">
+           <string>Reset Options</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+       </layout>
       </item>
      </layout>
     </widget>
diff --git a/src/plugins/cpptools/cpptoolsconstants.h b/src/plugins/cpptools/cpptoolsconstants.h
index d6130297f2..819dde85fc 100644
--- a/src/plugins/cpptools/cpptoolsconstants.h
+++ b/src/plugins/cpptools/cpptoolsconstants.h
@@ -55,6 +55,7 @@ enum { lowerCaseFilesDefault = 1 };
 const char CPPTOOLS_SORT_EDITOR_DOCUMENT_OUTLINE[] = "SortedMethodOverview";
 const char CPPTOOLS_MODEL_MANAGER_SUPPORTERS_KEY[] = "ModelManagerSupporters";
 const char CPPTOOLS_MODEL_MANAGER_PCH_USAGE[] = "PCHUsage";
+const char CPPTOOLS_EXTRA_CLANG_OPTIONS[] = "ExtraClangOptions";
 
 const char CPP_CODE_STYLE_SETTINGS_ID[] = "A.Cpp.Code Style";
 const char CPP_CODE_STYLE_SETTINGS_NAME[] = QT_TRANSLATE_NOOP("CppTools", "Code Style");
-- 
GitLab