From 20b5c3b2c88e04f2d87dc2d0cb54aa2b5a13ec75 Mon Sep 17 00:00:00 2001 From: Sergey Shambir Date: Sun, 3 Mar 2013 21:53:38 +0400 Subject: [PATCH] ToolChain: added warningFlags() method Converts toolchain-specific flags in QFlags. Will be useful for ClangCodeModel. Change-Id: I2cff650c952f7c41d3a27535a27fa52b932a0b92 Reviewed-by: Erik Verbruggen --- .../projectexplorer/abstractmsvctoolchain.cpp | 119 ++++++++++++++++++ .../projectexplorer/abstractmsvctoolchain.h | 16 +++ .../projectexplorer/customtoolchain.cpp | 6 + src/plugins/projectexplorer/customtoolchain.h | 1 + src/plugins/projectexplorer/gcctoolchain.cpp | 97 ++++++++++++++ src/plugins/projectexplorer/gcctoolchain.h | 17 +++ src/plugins/projectexplorer/toolchain.cpp | 5 + src/plugins/projectexplorer/toolchain.h | 31 +++++ 8 files changed, 292 insertions(+) diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp index 9d0e6265906..38856093785 100644 --- a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp @@ -101,6 +101,55 @@ ToolChain::CompilerFlags AbstractMsvcToolChain::compilerFlags(const QStringList } } +/** + * Converts MSVC warning flags to clang flags. + * @see http://msdn.microsoft.com/en-us/library/thxezb7y.aspx + */ +AbstractMsvcToolChain::WarningFlags AbstractMsvcToolChain::warningFlags(const QStringList &cflags) const +{ + WarningFlags flags; + foreach (QString flag, cflags) { + if (!flag.isEmpty() && flag[0] == QLatin1Char('-')) + flag[0] = QLatin1Char('/'); + + if (flag == QLatin1String("/WX")) + flags |= WarningsAsErrors; + else if (flag == QLatin1String("/W0") || flag == QLatin1String("/w")) + inferWarningsForLevel(0, flags); + else if (flag == QLatin1String("/W1")) + inferWarningsForLevel(1, flags); + else if (flag == QLatin1String("/W2")) + inferWarningsForLevel(2, flags); + else if (flag == QLatin1String("/W3") || flag == QLatin1String("/W4") || flag == QLatin1String("/Wall")) + inferWarningsForLevel(3, flags); + + WarningFlagAdder add(flag, flags); + if (add.triggered()) + continue; + // http://msdn.microsoft.com/en-us/library/ay4h0tc9.aspx + add(4263, WarnOverloadedVirtual); + // http://msdn.microsoft.com/en-us/library/ytxde1x7.aspx + add(4230, WarnIgnoredQualfiers); + // not exact match, http://msdn.microsoft.com/en-us/library/0hx5ckb0.aspx + add(4258, WarnHiddenLocals); + // http://msdn.microsoft.com/en-us/library/wzxffy8c.aspx + add(4265, WarnNonVirtualDestructor); + // http://msdn.microsoft.com/en-us/library/y92ktdf2%28v=vs.90%29.aspx + add(4018, WarnSignedComparison); + // http://msdn.microsoft.com/en-us/library/w099eeey%28v=vs.90%29.aspx + add(4068, WarnUnknownPragma); + // http://msdn.microsoft.com/en-us/library/26kb9fy0%28v=vs.80%29.aspx + add(4100, WarnUnusedParams); + // http://msdn.microsoft.com/en-us/library/c733d5h9%28v=vs.90%29.aspx + add(4101, WarnUnusedLocals); + // http://msdn.microsoft.com/en-us/library/xb1db44s%28v=vs.90%29.aspx + add(4189, WarnUnusedLocals); + // http://msdn.microsoft.com/en-us/library/ttcz0bys%28v=vs.90%29.aspx + add(4996, WarnDeprecated); + } + return flags; +} + QList AbstractMsvcToolChain::systemHeaderPaths(const QStringList &cxxflags, const Utils::FileName &sysRoot) const { Q_UNUSED(cxxflags); @@ -276,6 +325,30 @@ bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env, return true; } +/** + * Infers warnings settings on warning level set + * @see http://msdn.microsoft.com/en-us/library/23k5d385.aspx + */ +void AbstractMsvcToolChain::inferWarningsForLevel(int warningLevel, WarningFlags &flags) +{ + // reset all except unrelated flag + flags = flags & WarningsAsErrors; + + if (warningLevel >= 1) { + flags |= WarningFlags(WarningsDefault | WarnIgnoredQualfiers | WarnHiddenLocals | WarnUnknownPragma); + } + if (warningLevel >= 2) { + flags |= WarningsAll; + } + if (warningLevel >= 3) { + flags |= WarningFlags(WarningsExtra | WarnNonVirtualDestructor | WarnSignedComparison + | WarnUnusedLocals | WarnDeprecated); + } + if (warningLevel >= 4) { + flags |= WarnUnusedParams; + } +} + bool AbstractMsvcToolChain::operator ==(const ToolChain &other) const { if (!ToolChain::operator ==(other)) @@ -286,6 +359,52 @@ bool AbstractMsvcToolChain::operator ==(const ToolChain &other) const && m_vcvarsBat == msvcTc->m_vcvarsBat; } +AbstractMsvcToolChain::WarningFlagAdder::WarningFlagAdder(const QString &flag, + ToolChain::WarningFlags &flags) : + m_flags(flags), + m_triggered(false) +{ + if (flag.startsWith(QLatin1String("-wd"))) { + m_doesEnable = false; + } else if (flag.startsWith(QLatin1String("-w"))) { + m_doesEnable = true; + } else { + m_triggered = true; + return; + } + bool ok = false; + if (m_doesEnable) + m_warningCode = flag.mid(2).toInt(&ok); + else + m_warningCode = flag.mid(3).toInt(&ok); + if (!ok) + m_triggered = true; +} + +void AbstractMsvcToolChain::WarningFlagAdder::operator ()(int warningCode, ToolChain::WarningFlags flagsSet) +{ + if (m_triggered) + return; + if (warningCode == m_warningCode) + { + m_triggered = true; + if (m_doesEnable) + m_flags |= flagsSet; + else + m_flags &= ~flagsSet; + } +} + +void AbstractMsvcToolChain::WarningFlagAdder::operator ()(int warningCode, ToolChain::WarningFlag flag) +{ + (*this)(warningCode, WarningFlags(flag)); +} + +bool AbstractMsvcToolChain::WarningFlagAdder::triggered() const +{ + return m_triggered; +} + } // namespace Internal } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.h b/src/plugins/projectexplorer/abstractmsvctoolchain.h index a35aea1d569..bcf405e4172 100644 --- a/src/plugins/projectexplorer/abstractmsvctoolchain.h +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.h @@ -52,6 +52,7 @@ public: QByteArray predefinedMacros(const QStringList &cxxflags) const; CompilerFlags compilerFlags(const QStringList &cxxflags) const; + WarningFlags warningFlags(const QStringList &cflags) const; QList systemHeaderPaths(const QStringList &cxxflags, const Utils::FileName &sysRoot) const; void addToEnvironment(Utils::Environment &env) const; @@ -71,6 +72,21 @@ public: QMap &envPairs); protected: + class WarningFlagAdder + { + int m_warningCode; + WarningFlags &m_flags; + bool m_doesEnable; + bool m_triggered; + public: + WarningFlagAdder(const QString &flag, WarningFlags &flags); + void operator ()(int warningCode, WarningFlags flagsSet); + void operator ()(int warningCode, WarningFlag flag); + + bool triggered() const; + }; + + static void inferWarningsForLevel(int warningLevel, WarningFlags &flags); virtual Utils::Environment readEnvironmentSetting(Utils::Environment& env) const = 0; virtual QByteArray msvcPredefinedMacros(const QStringList cxxflags, const Utils::Environment& env) const; diff --git a/src/plugins/projectexplorer/customtoolchain.cpp b/src/plugins/projectexplorer/customtoolchain.cpp index 1c410d2e018..a3032a63a17 100644 --- a/src/plugins/projectexplorer/customtoolchain.cpp +++ b/src/plugins/projectexplorer/customtoolchain.cpp @@ -145,6 +145,12 @@ ToolChain::CompilerFlags CustomToolChain::compilerFlags(const QStringList &cxxfl return NO_FLAGS; } +ToolChain::WarningFlags CustomToolChain::warningFlags(const QStringList &cxxflags) const +{ + Q_UNUSED(cxxflags); + return WarningFlags(WarningsDefault); +} + const QStringList &CustomToolChain::rawPredefinedMacros() const { return m_predefinedMacros; diff --git a/src/plugins/projectexplorer/customtoolchain.h b/src/plugins/projectexplorer/customtoolchain.h index 2f2ee6ece61..97489bd54f2 100644 --- a/src/plugins/projectexplorer/customtoolchain.h +++ b/src/plugins/projectexplorer/customtoolchain.h @@ -67,6 +67,7 @@ public: QByteArray predefinedMacros(const QStringList &cxxflags) const; CompilerFlags compilerFlags(const QStringList &cxxflags) const; + WarningFlags warningFlags(const QStringList &cxxflags) const; const QStringList &rawPredefinedMacros() const; void setPredefinedMacros(const QStringList &list); diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 9dcea8f2cac..9e3779dfcdb 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -436,6 +436,51 @@ ToolChain::CompilerFlags GccToolChain::compilerFlags(const QStringList &cxxflags return NO_FLAGS; } +GccToolChain::WarningFlags GccToolChain::warningFlags(const QStringList &cflags) const +{ + // based on 'LC_ALL="en" gcc -Q --help=warnings | grep enabled' + WarningFlags flags(WarnDeprecated | WarnIgnoredQualfiers + | WarnSignedComparison | WarnUninitializedVars); + WarningFlags groupWall(WarningsAll | WarnUnknownPragma |WarnUnusedFunctions + | WarnUnusedLocals | WarnUnusedResult | WarnUnusedValue + | WarnSignedComparison | WarnUninitializedVars); + WarningFlags groupWextra(WarningsExtra | WarnIgnoredQualfiers | WarnUnusedParams); + + foreach (const QString &flag, cflags) { + if (flag == QLatin1String("--all-warnings")) + flags |= groupWall; + else if (flag == QLatin1String("--extra-warnings")) + flags |= groupWextra; + + WarningFlagAdder add(flag, flags); + if (add.triggered()) + continue; + + // supported by clang too + add("error", WarningsAsErrors); + add("all", groupWall); + add("extra", groupWextra); + add("deprecated", WarnDeprecated); + add("effc++", WarnEffectiveCxx); + add("ignored-qualifiers", WarnIgnoredQualfiers); + add("non-virtual-dtor", WarnNonVirtualDestructor); + add("overloaded-virtual", WarnOverloadedVirtual); + add("shadow", WarnHiddenLocals); + add("sign-compare", WarnSignedComparison); + add("unknown-pragmas", WarnUnknownPragma); + add("unused", ToolChain::WarningFlag( + WarnUnusedFunctions | WarnUnusedLocals | WarnUnusedParams + | WarnUnusedResult | WarnUnusedValue)); + add("unused-function", WarnUnusedFunctions); + add("unused-variable", WarnUnusedLocals); + add("unused-parameter", WarnUnusedParams); + add("unused-result", WarnUnusedResult); + add("unused-value", WarnUnusedValue); + add("uninitialized", WarnUninitializedVars); + } + return flags; +} + QList GccToolChain::systemHeaderPaths(const QStringList &cxxflags, const Utils::FileName &sysRoot) const { if (m_headerPaths.isEmpty()) { @@ -827,6 +872,18 @@ QString ClangToolChain::makeCommand(const Utils::Environment &environment) const return makes.first(); } +ToolChain::WarningFlags ClangToolChain::warningFlags(const QStringList &cflags) const +{ + WarningFlags flags = GccToolChain::warningFlags(cflags);; + foreach (const QString &flag, cflags) { + if (flag == QLatin1String("-Wdocumentation")) + flags |= WarnDocumentation; + if (flag == QLatin1String("-Wno-documentation")) + flags &= ~WarnDocumentation; + } + return flags; +} + QList ClangToolChain::suggestedMkspecList() const { Abi abi = targetAbi(); @@ -1089,6 +1146,46 @@ GccToolChain *Internal::LinuxIccToolChainFactory::createToolChain(bool autoDetec return new LinuxIccToolChain(autoDetect); } +GccToolChain::WarningFlagAdder::WarningFlagAdder(const QString &flag, ToolChain::WarningFlags &flags) : + m_flags(flags), + m_triggered(false) +{ + if (!flag.startsWith(QLatin1String("-W"))) { + m_triggered = true; + return; + } + + m_doesEnable = !flag.startsWith(QLatin1String("-Wno-")); + if (m_doesEnable) + m_flagUtf8 = flag.mid(2).toUtf8(); + else + m_flagUtf8 = flag.mid(5).toUtf8(); +} + +void GccToolChain::WarningFlagAdder::operator ()(const char name[], ToolChain::WarningFlags flagsSet) +{ + if (m_triggered) + return; + if (0 == strcmp(m_flagUtf8.data(), name)) + { + m_triggered = true; + if (m_doesEnable) + m_flags |= flagsSet; + else + m_flags &= ~flagsSet; + } +} + +void GccToolChain::WarningFlagAdder::operator ()(const char name[], ToolChain::WarningFlag flag) +{ + (*this)(name, WarningFlags(flag)); +} + +bool GccToolChain::WarningFlagAdder::triggered() const +{ + return m_triggered; +} + } // namespace ProjectExplorer // Unit tests: diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h index 07a2d5c58d5..ddba601ad3c 100644 --- a/src/plugins/projectexplorer/gcctoolchain.h +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -66,6 +66,7 @@ public: QByteArray predefinedMacros(const QStringList &cxxflags) const; CompilerFlags compilerFlags(const QStringList &cxxflags) const; + WarningFlags warningFlags(const QStringList &cflags) const; QList systemHeaderPaths(const QStringList &cxxflags, const Utils::FileName &sysRoot) const; void addToEnvironment(Utils::Environment &env) const; @@ -100,6 +101,20 @@ protected: static const int PREDEFINED_MACROS_CACHE_SIZE; mutable GccCache m_predefinedMacros; + class WarningFlagAdder + { + QByteArray m_flagUtf8; + WarningFlags &m_flags; + bool m_doesEnable; + bool m_triggered; + public: + WarningFlagAdder(const QString &flag, WarningFlags &flags); + void operator ()(const char name[], WarningFlags flagsSet); + void operator ()(const char name[], WarningFlag flag); + + bool triggered() const; + }; + private: GccToolChain(bool autodetect); @@ -127,6 +142,8 @@ public: QString typeDisplayName() const; QString makeCommand(const Utils::Environment &environment) const; + WarningFlags warningFlags(const QStringList &cflags) const; + IOutputParser *outputParser() const; ToolChain *clone() const; diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index 8a5a6be3558..300812b2ee4 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -215,6 +215,11 @@ QList ToolChain::validateKit(const Kit *) const \brief Name used to display the name of the tool chain that will be created. */ +/*! + \fn QStringList ProjectExplorer::ToolChain::clangParserFlags(const QStringList &cxxflags) const = 0 + \brief Converts toolchain-specific flags to list flags that tunes libclang parser +*/ + /*! \fn bool ProjectExplorer::ToolChainFactory::canRestore(const QVariantMap &data) \brief Used by the ToolChainManager to restore user-generated tool chains. diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index b45de47853c..41c31fff7d7 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -87,6 +87,37 @@ public: STD_CXX11 = 1 }; virtual CompilerFlags compilerFlags(const QStringList &cxxflags) const = 0; + + enum WarningFlag { + // General settings + WarningsAsErrors, + WarningsDefault, + WarningsAll, + WarningsExtra, + WarningsPedantic, + + // Any language + WarnUnusedLocals, + WarnUnusedParams, + WarnUnusedFunctions, + WarnUnusedResult, + WarnUnusedValue, + WarnDocumentation, + WarnUninitializedVars, + WarnHiddenLocals, + WarnUnknownPragma, + WarnDeprecated, + WarnSignedComparison, + WarnIgnoredQualfiers, + + // C++ + WarnOverloadedVirtual, + WarnEffectiveCxx, + WarnNonVirtualDestructor + }; + Q_DECLARE_FLAGS(WarningFlags, WarningFlag) + + virtual WarningFlags warningFlags(const QStringList &cflags) const = 0; virtual QList systemHeaderPaths(const QStringList &cxxflags, const Utils::FileName &sysRoot) const = 0; virtual void addToEnvironment(Utils::Environment &env) const = 0;