diff options
28 files changed, 317 insertions, 208 deletions
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp index c211fcc471..fc4850b84f 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp @@ -276,10 +276,8 @@ void AutotoolsProject::updateCppCodeModel() CppTools::ProjectPart::QtVersion activeQtVersion = CppTools::ProjectPart::NoQt; if (QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k)) { - if (qtVersion->qtVersion() <= QtSupport::QtVersionNumber(4,8,6)) - activeQtVersion = CppTools::ProjectPart::Qt4_8_6AndOlder; - else if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) - activeQtVersion = CppTools::ProjectPart::Qt4Latest; + if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) + activeQtVersion = CppTools::ProjectPart::Qt4; else activeQtVersion = CppTools::ProjectPart::Qt5; } diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index ddf9ba6d89..598a0f7b4a 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -286,10 +286,8 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc) CppTools::ProjectPart::QtVersion activeQtVersion = CppTools::ProjectPart::NoQt; if (QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k)) { - if (qtVersion->qtVersion() <= QtSupport::QtVersionNumber(4,8,6)) - activeQtVersion = CppTools::ProjectPart::Qt4_8_6AndOlder; - else if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) - activeQtVersion = CppTools::ProjectPart::Qt4Latest; + if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) + activeQtVersion = CppTools::ProjectPart::Qt4; else activeQtVersion = CppTools::ProjectPart::Qt5; } diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp index 487652aeb9..47c66df91a 100644 --- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp +++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.cpp @@ -253,7 +253,7 @@ CompilationDatabaseProject::CompilationDatabaseProject(const Utils::FileName &pr tcInfo.targetTriple = tc->originalTargetTriple(); tcInfo.sysRootPath = ProjectExplorer::SysRootKitInformation::sysRoot(kit).toString(); tcInfo.headerPathsRunner = tc->createBuiltInHeaderPathsRunner(); - tcInfo.predefinedMacrosRunner = tc->createPredefinedMacrosRunner(); + tcInfo.macroInspectionRunner = tc->createMacroInspectionRunner(); m_cppCodeModelUpdater->update({this, tcInfo, tcInfo, rpps}); diff --git a/src/plugins/cppcheck/cppchecktool.cpp b/src/plugins/cppcheck/cppchecktool.cpp index 28111cd3f6..5288e0f4c1 100644 --- a/src/plugins/cppcheck/cppchecktool.cpp +++ b/src/plugins/cppcheck/cppchecktool.cpp @@ -148,6 +148,9 @@ QStringList CppcheckTool::additionalArguments(const CppTools::ProjectPart &part) case Version::C11: result.push_back("--std=c11 --language=c"); break; + case Version::C18: + result.push_back("--language=c"); + break; case Version::CXX03: result.push_back("--std=c++03 --language=c++"); break; @@ -159,6 +162,7 @@ QStringList CppcheckTool::additionalArguments(const CppTools::ProjectPart &part) break; case Version::CXX98: case Version::CXX17: + case Version::CXX2a: result.push_back("--language=c++"); break; } diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp index e722722e25..b05bd09d1f 100644 --- a/src/plugins/cpptools/compileroptionsbuilder.cpp +++ b/src/plugins/cpptools/compileroptionsbuilder.cpp @@ -408,6 +408,10 @@ void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtension case ProjectPart::C11: opts << (gnuExtensions ? QLatin1String("-std=gnu11") : QLatin1String("-std=c11")); break; + case ProjectPart::C18: + // Clang 6, 7 and current trunk do not accept "gnu18"/"c18", so use the "*17" variants. + opts << (gnuExtensions ? QLatin1String("-std=gnu17") : QLatin1String("-std=c17")); + break; case ProjectPart::CXX11: opts << (gnuExtensions ? QLatin1String("-std=gnu++11") : QLatin1String("-std=c++11")); break; @@ -423,6 +427,9 @@ void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtension case ProjectPart::CXX17: opts << (gnuExtensions ? QLatin1String("-std=gnu++17") : QLatin1String("-std=c++17")); break; + case ProjectPart::CXX2a: + opts << (gnuExtensions ? QLatin1String("-std=gnu++2a") : QLatin1String("-std=c++2a")); + break; } if (languageExtensions & ProjectPart::MicrosoftExtensions) @@ -588,6 +595,11 @@ QString CompilerOptionsBuilder::includeOption() const bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro ¯o) const { + // Avoid setting __cplusplus & co as this might conflict with other command line flags. + // Clang should set __cplusplus based on -std= and -fms-compatibility-version version. + QTC_ASSERT(macro.key != "__cplusplus", return true); + QTC_ASSERT(macro.key != "__STDC_VERSION__", return true); + // Ignore for all compiler toolchains since LLVM has it's own implementation for // __has_include(STR) and __has_include_next(STR) if (macro.key.startsWith("__has_include")) diff --git a/src/plugins/cpptools/cppcodemodelinspectordumper.cpp b/src/plugins/cpptools/cppcodemodelinspectordumper.cpp index 6a0c1fe124..540ac99104 100644 --- a/src/plugins/cpptools/cppcodemodelinspectordumper.cpp +++ b/src/plugins/cpptools/cppcodemodelinspectordumper.cpp @@ -110,11 +110,13 @@ QString Utils::toString(ProjectPart::LanguageVersion languageVersion) CASE_LANGUAGEVERSION(C89); CASE_LANGUAGEVERSION(C99); CASE_LANGUAGEVERSION(C11); + CASE_LANGUAGEVERSION(C18); CASE_LANGUAGEVERSION(CXX98); CASE_LANGUAGEVERSION(CXX03); CASE_LANGUAGEVERSION(CXX11); CASE_LANGUAGEVERSION(CXX14); CASE_LANGUAGEVERSION(CXX17); + CASE_LANGUAGEVERSION(CXX2a); // no default to get a compiler warning if anything is added } #undef CASE_LANGUAGEVERSION @@ -146,8 +148,7 @@ QString Utils::toString(ProjectPart::QtVersion qtVersion) switch (qtVersion) { CASE_QTVERSION(UnknownQt); CASE_QTVERSION(NoQt); - CASE_QTVERSION(Qt4_8_6AndOlder); - CASE_QTVERSION(Qt4Latest); + CASE_QTVERSION(Qt4); CASE_QTVERSION(Qt5); // no default to get a compiler warning if anything is added } diff --git a/src/plugins/cpptools/cppprojectinfogenerator.cpp b/src/plugins/cpptools/cppprojectinfogenerator.cpp index fd1c928090..8d04f2429e 100644 --- a/src/plugins/cpptools/cppprojectinfogenerator.cpp +++ b/src/plugins/cpptools/cppprojectinfogenerator.cpp @@ -30,6 +30,8 @@ #include <projectexplorer/headerpath.h> #include <projectexplorer/projectexplorerconstants.h> +#include <utils/qtcassert.h> + namespace CppTools { namespace Internal { @@ -39,9 +41,11 @@ class ToolChainEvaluator { public: ToolChainEvaluator(ProjectPart &projectPart, + Language language, const RawProjectPartFlags &flags, const ToolChainInfo &tcInfo) : m_projectPart(projectPart) + , m_language(language) , m_flags(flags) , m_tcInfo(tcInfo) { @@ -61,11 +65,20 @@ public: if (m_projectPart.toolchainType == ProjectExplorer::Constants::COMPILATION_DATABASE_TOOLCHAIN_TYPEID) m_projectPart.extraCodeModelFlags = m_flags.commandLineFlags; - mapLanguageVersion(); - mapLanguageExtensions(); + if (m_tcInfo.macroInspectionRunner) { + auto macroInspectionReport = m_tcInfo.macroInspectionRunner(m_flags.commandLineFlags); + m_projectPart.toolChainMacros = macroInspectionReport.macros; + m_projectPart.languageVersion = static_cast<ProjectPart::LanguageVersion>( + macroInspectionReport.languageVersion); + } else { // No compiler set in kit. + if (m_language == Language::C) + m_projectPart.languageVersion = ProjectPart::LanguageVersion::LatestCVersion; + if (m_language == Language::CXX) + m_projectPart.languageVersion = ProjectPart::LanguageVersion::LatestCxxVersion; + } + mapLanguageExtensions(); addHeaderPaths(); - addDefines(); } private: @@ -76,27 +89,6 @@ private: : ProjectPart::WordWidth32Bit; } - void mapLanguageVersion() - { - using namespace ProjectExplorer; - - const ToolChain::CompilerFlags &compilerFlags = m_flags.compilerFlags; - ProjectPart::LanguageVersion &languageVersion = m_projectPart.languageVersion; - - if (compilerFlags & ToolChain::StandardC11) - languageVersion = ProjectPart::C11; - else if (compilerFlags & ToolChain::StandardC99) - languageVersion = ProjectPart::C99; - else if (compilerFlags & ToolChain::StandardCxx17) - languageVersion = ProjectPart::CXX17; - else if (compilerFlags & ToolChain::StandardCxx14) - languageVersion = ProjectPart::CXX14; - else if (compilerFlags & ToolChain::StandardCxx11) - languageVersion = ProjectPart::CXX11; - else if (compilerFlags & ToolChain::StandardCxx98) - languageVersion = ProjectPart::CXX98; - } - void mapLanguageExtensions() { using namespace ProjectExplorer; @@ -133,16 +125,9 @@ private: } } - void addDefines() - { - if (!m_tcInfo.predefinedMacrosRunner) - return; // No compiler set in kit. - - m_projectPart.toolChainMacros = m_tcInfo.predefinedMacrosRunner(m_flags.commandLineFlags); - } - private: ProjectPart &m_projectPart; + const Language m_language; const RawProjectPartFlags &m_flags; const ToolChainInfo &m_tcInfo; }; @@ -205,15 +190,12 @@ QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts(const RawProj const ProjectPart::Ptr part = projectPartFromRawProjectPart(rawProjectPart, m_projectUpdateInfo.project); - ProjectPart::LanguageVersion defaultVersion = ProjectPart::LatestCxxVersion; - if (rawProjectPart.qtVersion == ProjectPart::Qt4_8_6AndOlder) - defaultVersion = ProjectPart::CXX11; if (cat.hasCxxSources()) { result << createProjectPart(rawProjectPart, part, cat.cxxSources(), cat.partName("C++"), - defaultVersion, + Language::CXX, ProjectPart::NoExtensions); } @@ -222,7 +204,7 @@ QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts(const RawProj part, cat.objcxxSources(), cat.partName("Obj-C++"), - defaultVersion, + Language::CXX, ProjectPart::ObjectiveCExtensions); } @@ -231,7 +213,7 @@ QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts(const RawProj part, cat.cSources(), cat.partName("C"), - ProjectPart::LatestCVersion, + Language::C, ProjectPart::NoExtensions); } @@ -240,7 +222,7 @@ QVector<ProjectPart::Ptr> ProjectInfoGenerator::createProjectParts(const RawProj part, cat.objcSources(), cat.partName("Obj-C"), - ProjectPart::LatestCVersion, + Language::C, ProjectPart::ObjectiveCExtensions); } } @@ -251,17 +233,16 @@ ProjectPart::Ptr ProjectInfoGenerator::createProjectPart(const RawProjectPart &r const ProjectPart::Ptr &templateProjectPart, const ProjectFiles &projectFiles, const QString &partName, - ProjectPart::LanguageVersion languageVersion, + Language language, ProjectPart::LanguageExtensions languageExtensions) { ProjectPart::Ptr part(templateProjectPart->copy()); part->displayName = partName; part->files = projectFiles; - part->languageVersion = languageVersion; RawProjectPartFlags flags; ToolChainInfo tcInfo; - if (languageVersion <= ProjectPart::LatestCVersion) { + if (language == Language::C) { flags = rawProjectPart.flagsForC; tcInfo = m_projectUpdateInfo.cToolChainInfo; } @@ -271,7 +252,7 @@ ProjectPart::Ptr ProjectInfoGenerator::createProjectPart(const RawProjectPart &r tcInfo = m_projectUpdateInfo.cxxToolChainInfo; } // TODO: If no toolchain is set, show a warning - ToolChainEvaluator evaluator(*part.data(), flags, tcInfo); + ToolChainEvaluator evaluator(*part.data(), language, flags, tcInfo); evaluator.evaluate(); part->languageExtensions |= languageExtensions; diff --git a/src/plugins/cpptools/cppprojectinfogenerator.h b/src/plugins/cpptools/cppprojectinfogenerator.h index 6f81eaf85f..963c9a748b 100644 --- a/src/plugins/cpptools/cppprojectinfogenerator.h +++ b/src/plugins/cpptools/cppprojectinfogenerator.h @@ -32,6 +32,8 @@ namespace CppTools { namespace Internal { +enum class Language { C, CXX }; + class ProjectInfoGenerator { public: @@ -46,7 +48,7 @@ private: const ProjectPart::Ptr &templateProjectPart, const ProjectFiles &projectFiles, const QString &partName, - ProjectPart::LanguageVersion languageVersion, + Language language, ProjectPart::LanguageExtensions languageExtensions); private: diff --git a/src/plugins/cpptools/projectinfo.cpp b/src/plugins/cpptools/projectinfo.cpp index a51caebe11..c39449fef7 100644 --- a/src/plugins/cpptools/projectinfo.cpp +++ b/src/plugins/cpptools/projectinfo.cpp @@ -48,7 +48,7 @@ ToolChainInfo::ToolChainInfo(const ProjectExplorer::ToolChain *toolChain, // they can be run from a worker thread. sysRootPath = ProjectExplorer::SysRootKitInformation::sysRoot(kit).toString(); headerPathsRunner = toolChain->createBuiltInHeaderPathsRunner(); - predefinedMacrosRunner = toolChain->createPredefinedMacrosRunner(); + macroInspectionRunner = toolChain->createMacroInspectionRunner(); } } diff --git a/src/plugins/cpptools/projectinfo.h b/src/plugins/cpptools/projectinfo.h index 38bf509cba..a69ffd8fdf 100644 --- a/src/plugins/cpptools/projectinfo.h +++ b/src/plugins/cpptools/projectinfo.h @@ -58,7 +58,7 @@ public: QString sysRootPath; // For headerPathsRunner. ProjectExplorer::ToolChain::BuiltInHeaderPathsRunner headerPathsRunner; - ProjectExplorer::ToolChain::PredefinedMacrosRunner predefinedMacrosRunner; + ProjectExplorer::ToolChain::MacroInspectionRunner macroInspectionRunner; }; class CPPTOOLS_EXPORT ProjectUpdateInfo diff --git a/src/plugins/cpptools/projectpart.h b/src/plugins/cpptools/projectpart.h index ce017abc79..8d04e71ff3 100644 --- a/src/plugins/cpptools/projectpart.h +++ b/src/plugins/cpptools/projectpart.h @@ -49,17 +49,20 @@ namespace CppTools { class CPPTOOLS_EXPORT ProjectPart { public: + // Keep in sync with Toolchain::LanguageVersion! enum LanguageVersion { C89, C99, C11, - LatestCVersion = C11, + C18, + LatestCVersion = C18, CXX98, CXX03, CXX11, CXX14, CXX17, - LatestCxxVersion = CXX17, + CXX2a, + LatestCxxVersion = CXX2a, }; enum LanguageExtension { @@ -81,8 +84,7 @@ public: enum QtVersion { UnknownQt = -1, NoQt, - Qt4_8_6AndOlder, - Qt4Latest, + Qt4, Qt5 }; diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp index edeac3eec4..b99d037e65 100644 --- a/src/plugins/genericprojectmanager/genericproject.cpp +++ b/src/plugins/genericprojectmanager/genericproject.cpp @@ -436,10 +436,8 @@ void GenericProject::refreshCppCodeModel() CppTools::ProjectPart::QtVersion activeQtVersion = CppTools::ProjectPart::NoQt; if (QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(activeTarget()->kit())) { - if (qtVersion->qtVersion() <= QtSupport::QtVersionNumber(4,8,6)) - activeQtVersion = CppTools::ProjectPart::Qt4_8_6AndOlder; - else if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) - activeQtVersion = CppTools::ProjectPart::Qt4Latest; + if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) + activeQtVersion = CppTools::ProjectPart::Qt4; else activeQtVersion = CppTools::ProjectPart::Qt5; } diff --git a/src/plugins/nim/project/nimtoolchain.cpp b/src/plugins/nim/project/nimtoolchain.cpp index 01147f4fa1..ec1651a682 100644 --- a/src/plugins/nim/project/nimtoolchain.cpp +++ b/src/plugins/nim/project/nimtoolchain.cpp @@ -77,9 +77,9 @@ bool NimToolChain::isValid() const return fi.isExecutable(); } -ToolChain::PredefinedMacrosRunner NimToolChain::createPredefinedMacrosRunner() const +ToolChain::MacroInspectionRunner NimToolChain::createMacroInspectionRunner() const { - return ToolChain::PredefinedMacrosRunner(); + return ToolChain::MacroInspectionRunner(); } Macros NimToolChain::predefinedMacros(const QStringList &) const diff --git a/src/plugins/nim/project/nimtoolchain.h b/src/plugins/nim/project/nimtoolchain.h index 7b25e993de..4f866d5f27 100644 --- a/src/plugins/nim/project/nimtoolchain.h +++ b/src/plugins/nim/project/nimtoolchain.h @@ -40,7 +40,7 @@ public: ProjectExplorer::Abi targetAbi() const override; bool isValid() const override; - PredefinedMacrosRunner createPredefinedMacrosRunner() const override; + MacroInspectionRunner createMacroInspectionRunner() const override; ProjectExplorer::Macros predefinedMacros(const QStringList &flags) const final; CompilerFlags compilerFlags(const QStringList &flags) const final; ProjectExplorer::WarningFlags warningFlags(const QStringList &flags) const final; diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp index 4bd77d1462..151c4400ef 100644 --- a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp @@ -99,23 +99,88 @@ QString AbstractMsvcToolChain::originalTargetTriple() const : QLatin1String("i686-pc-windows-msvc"); } -ToolChain::PredefinedMacrosRunner AbstractMsvcToolChain::createPredefinedMacrosRunner() const +// +// We want to detect the language version based on the predefined macros. +// Unfortunately MSVC does not conform to standard when it comes to the predefined +// __cplusplus macro - it reports "199711L", even for newer language versions. +// +// However: +// * For >= Visual Studio 2015 Update 3 predefines _MSVC_LANG which has the proper value +// of __cplusplus. +// See https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017 +// * For >= Visual Studio 2017 Version 15.7 __cplusplus is correct once /Zc:__cplusplus +// is provided on the command line. Then __cplusplus == _MSVC_LANG. +// See https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus +// +// We rely on _MSVC_LANG if possible, otherwise on some hard coded language versions +// depending on _MSC_VER. +// +// For _MSV_VER values, see https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017. +// +ToolChain::LanguageVersion static languageVersionForMsvc(const Core::Id &language, + const Macros ¯os) +{ + using LanguageVersion = ToolChain::LanguageVersion; + + int mscVer = -1; + QByteArray msvcLang; + for (const ProjectExplorer::Macro ¯o : macros) { + if (macro.key == "_MSVC_LANG") + msvcLang = macro.value; + if (macro.key == "_MSC_VER") + mscVer = macro.value.toInt(nullptr); + } + QTC_CHECK(mscVer > 0); + + if (language == Constants::CXX_LANGUAGE_ID) { + if (!msvcLang.isEmpty()) // >= Visual Studio 2015 Update 3 + return ToolChain::cxxLanguageVersion(msvcLang); + if (mscVer >= 1800) // >= Visual Studio 2013 (12.0) + return LanguageVersion::CXX14; + if (mscVer >= 1600) // >= Visual Studio 2010 (10.0) + return LanguageVersion::CXX11; + return LanguageVersion::CXX98; + } else if (language == Constants::C_LANGUAGE_ID) { + if (mscVer >= 1910) // >= Visual Studio 2017 RTW (15.0) + return LanguageVersion::C11; + return LanguageVersion::C99; + } else { + QTC_CHECK(false && "Unexpected toolchain language, assuming latest C++ we support."); + return LanguageVersion::LatestCxxVersion; + } +} + +Q_GLOBAL_STATIC_WITH_ARGS(const QVector<QByteArray>, unwantedMacrosMsvc, + ({"_MSVC_LANG", + "_MSC_BUILD", + "_MSC_FULL_VER", + "_MSC_VER"})) + +ToolChain::MacroInspectionRunner AbstractMsvcToolChain::createMacroInspectionRunner() const { Utils::Environment env(m_lastEnvironment); addToEnvironment(env); + const Core::Id lang = language(); // This runner must be thread-safe! - return [this, env](const QStringList &cxxflags) { + return [this, env, lang](const QStringList &cxxflags) { QMutexLocker locker(m_predefinedMacrosMutex); - if (m_predefinedMacros.isEmpty()) + if (m_predefinedMacros.isEmpty() || m_cxxFlags != cxxflags) { m_predefinedMacros = msvcPredefinedMacros(cxxflags, env); - return m_predefinedMacros; + m_cxxFlags = cxxflags; + } + + const QVector<Macro> filteredMacros = Utils::filtered(m_predefinedMacros, [](const Macro &m) { + return !ToolChain::isUnwantedMacro(m) && !unwantedMacrosMsvc->contains(m.key); + }); + return MacroInspectionReport{filteredMacros, + languageVersionForMsvc(lang, m_predefinedMacros)}; }; } ProjectExplorer::Macros AbstractMsvcToolChain::predefinedMacros(const QStringList &cxxflags) const { - return createPredefinedMacrosRunner()(cxxflags); + return createMacroInspectionRunner()(cxxflags).macros; } ToolChain::CompilerFlags AbstractMsvcToolChain::compilerFlags(const QStringList &cxxflags) const @@ -128,35 +193,6 @@ ToolChain::CompilerFlags AbstractMsvcToolChain::compilerFlags(const QStringList if (cxxflags.contains(QLatin1String("/Za"))) flags &= ~MicrosoftExtensions; - bool cLanguage = (language() == ProjectExplorer::Constants::C_LANGUAGE_ID); - - switch (m_abi.osFlavor()) { - case Abi::WindowsMsvc2010Flavor: - case Abi::WindowsMsvc2012Flavor: - if (cLanguage) - flags |= StandardC99; - else - flags |= StandardCxx11; - break; - case Abi::WindowsMsvc2013Flavor: - case Abi::WindowsMsvc2015Flavor: - if (cLanguage) - flags |= StandardC99; - else - flags |= StandardCxx14; - break; - case Abi::WindowsMsvc2017Flavor: - if (cLanguage) - flags |= StandardC11; - else if (cxxflags.contains("/std:c++17") || cxxflags.contains("/std:c++latest")) - flags |= StandardCxx17; - else - flags |= StandardCxx14; - break; - default: - break; - } - return flags; } diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.h b/src/plugins/projectexplorer/abstractmsvctoolchain.h index 2979e728cc..d949073f46 100644 --- a/src/plugins/projectexplorer/abstractmsvctoolchain.h +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.h @@ -53,7 +53,7 @@ public: QString originalTargetTriple() const override; - PredefinedMacrosRunner createPredefinedMacrosRunner() const override; + MacroInspectionRunner createMacroInspectionRunner() const override; Macros predefinedMacros(const QStringList &cxxflags) const override; CompilerFlags compilerFlags(const QStringList &cxxflags) const override; WarningFlags warningFlags(const QStringList &cflags) const override; @@ -99,8 +99,11 @@ protected: Utils::FileName m_debuggerCommand; + mutable QMutex *m_predefinedMacrosMutex = nullptr; mutable Macros m_predefinedMacros; + mutable QStringList m_cxxFlags; + mutable Utils::Environment m_lastEnvironment; // Last checked 'incoming' environment. mutable Utils::Environment m_resultEnvironment; // Resulting environment for VC mutable QMutex *m_headerPathsMutex = nullptr; diff --git a/src/plugins/projectexplorer/customtoolchain.cpp b/src/plugins/projectexplorer/customtoolchain.cpp index f9cb0a81a7..7b952e0fe2 100644 --- a/src/plugins/projectexplorer/customtoolchain.cpp +++ b/src/plugins/projectexplorer/customtoolchain.cpp @@ -116,12 +116,13 @@ bool CustomToolChain::isValid() const return true; } -ToolChain::PredefinedMacrosRunner CustomToolChain::createPredefinedMacrosRunner() const +ToolChain::MacroInspectionRunner CustomToolChain::createMacroInspectionRunner() const { const Macros theMacros = m_predefinedMacros; + const Core::Id lang = language(); // This runner must be thread-safe! - return [theMacros](const QStringList &cxxflags){ + return [theMacros, lang](const QStringList &cxxflags){ Macros macros = theMacros; for (const QString &cxxFlag : cxxflags) { if (cxxFlag.startsWith(QLatin1String("-D"))) @@ -130,20 +131,17 @@ ToolChain::PredefinedMacrosRunner CustomToolChain::createPredefinedMacrosRunner( macros.append({cxxFlag.mid(2).trimmed().toUtf8(), MacroType::Undefine}); } - return macros; + return MacroInspectionReport{macros, ToolChain::languageVersion(lang, macros)}; }; } Macros CustomToolChain::predefinedMacros(const QStringList &cxxflags) const { - return createPredefinedMacrosRunner()(cxxflags); + return createMacroInspectionRunner()(cxxflags).macros; } -ToolChain::CompilerFlags CustomToolChain::compilerFlags(const QStringList &cxxflags) const +ToolChain::CompilerFlags CustomToolChain::compilerFlags(const QStringList &) const { - for (const QString &cxx11Flag : m_cxx11Flags) - if (cxxflags.contains(cxx11Flag)) - return StandardCxx11; return NoFlags; } diff --git a/src/plugins/projectexplorer/customtoolchain.h b/src/plugins/projectexplorer/customtoolchain.h index 23abb2e730..28fd7a1828 100644 --- a/src/plugins/projectexplorer/customtoolchain.h +++ b/src/plugins/projectexplorer/customtoolchain.h @@ -71,7 +71,7 @@ public: bool isValid() const override; - PredefinedMacrosRunner createPredefinedMacrosRunner() const override; + MacroInspectionRunner createMacroInspectionRunner() const override; Macros predefinedMacros(const QStringList &cxxflags) const override; CompilerFlags compilerFlags(const QStringList &cxxflags) const override; WarningFlags warningFlags(const QStringList &cxxflags) const override; diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 622b477ca2..2fa6de6737 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -254,7 +254,7 @@ GccToolChain::GccToolChain(Detection d) : GccToolChain::GccToolChain(Core::Id typeId, Detection d) : ToolChain(typeId, d), - m_predefinedMacrosCache(std::make_shared<Cache<QVector<Macro>, 64>>()), + m_predefinedMacrosCache(std::make_shared<Cache<MacroInspectionReport, 64>>()), m_headerPathsCache(std::make_shared<Cache<HeaderPaths>>()) { } @@ -385,9 +385,7 @@ static Utils::FileName findLocalCompiler(const Utils::FileName &compilerPath, return path.isEmpty() ? compilerPath : path; } -Q_GLOBAL_STATIC_WITH_ARGS(const QVector<QByteArray>, unwantedMacros, ({"__cplusplus"})) - -ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() const +ToolChain::MacroInspectionRunner GccToolChain::createMacroInspectionRunner() const { // Using a clean environment breaks ccache/distcc/etc. Environment env = Environment::systemEnvironment(); @@ -396,7 +394,7 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c const QStringList platformCodeGenFlags = m_platformCodeGenFlags; OptionsReinterpreter reinterpretOptions = m_optionsReinterpreter; QTC_CHECK(reinterpretOptions); - std::shared_ptr<Cache<QVector<Macro>, 64>> macroCache = m_predefinedMacrosCache; + std::shared_ptr<Cache<MacroInspectionReport, 64>> macroCache = m_predefinedMacrosCache; Core::Id lang = language(); // This runner must be thread-safe! @@ -436,20 +434,22 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c } arguments = reinterpretOptions(arguments); - const Utils::optional<QVector<Macro>> cachedMacros = macroCache->check(arguments); + const Utils::optional<MacroInspectionReport> cachedMacros = macroCache->check(arguments); if (cachedMacros) return cachedMacros.value(); - const QVector<Macro> macros - = gccPredefinedMacros(findLocalCompiler(compilerCommand, env), - arguments, - env.toStringList()); + const Macros macros = gccPredefinedMacros(findLocalCompiler(compilerCommand, env), + arguments, + env.toStringList()); const QVector<Macro> filteredMacros = Utils::filtered(macros, [](const Macro &m) { - return !unwantedMacros->contains(m.key); + return !isUnwantedMacro(m); }); - macroCache->insert(arguments, filteredMacros); - qCDebug(gccLog) << "Reporting macros to code model:"; + const auto report = MacroInspectionReport{filteredMacros, languageVersion(lang, macros)}; + macroCache->insert(arguments, report); + + qCDebug(gccLog) << "MacroInspectionReport for code model:"; + qCDebug(gccLog) << "Language version:" << report.languageVersion; for (const Macro &m : filteredMacros) { qCDebug(gccLog) << compilerCommand.toUserOutput() << (lang == Constants::CXX_LANGUAGE_ID ? ": C++ [" : ": C [") @@ -457,7 +457,7 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c << QString::fromUtf8(m.toByteArray()); } - return filteredMacros; + return report; }; } @@ -472,7 +472,7 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c */ ProjectExplorer::Macros GccToolChain::predefinedMacros(const QStringList &cxxflags) const { - return createPredefinedMacrosRunner()(cxxflags); + return createMacroInspectionRunner()(cxxflags).macros; } /** @@ -487,55 +487,14 @@ ToolChain::CompilerFlags GccToolChain::compilerFlags(const QStringList &cxxflags foreach (const QString &flag, allCxxflags) { if (flag.startsWith("-std=")) { const QByteArray std = flag.mid(5).toLatin1(); - if (std == "c++98" || std == "c++03") { - flags &= ~CompilerFlags(StandardCxx11 | StandardCxx14 | StandardCxx17 | GnuExtensions); - flags |= StandardCxx98; - } else if (std == "gnu++98" || std == "gnu++03") { - flags &= ~CompilerFlags(StandardCxx11 | StandardCxx14 | StandardCxx17); - flags |= GnuExtensions; - } else if (std == "c++0x" || std == "c++11") { - flags |= StandardCxx11; - flags &= ~CompilerFlags(StandardCxx14 | StandardCxx17 | GnuExtensions); - } else if (std == "c++14" || std == "c++1y") { - flags |= StandardCxx14; - flags &= ~CompilerFlags(StandardCxx11 | StandardCxx17 | GnuExtensions); - } else if (std == "c++17" || std == "c++1z") { - flags |= StandardCxx17; - flags &= ~CompilerFlags(StandardCxx11 | StandardCxx14 | GnuExtensions); - } else if (std == "gnu++0x" || std == "gnu++11") { - flags |= CompilerFlags(StandardCxx11 | GnuExtensions); - flags &= ~CompilerFlags(StandardCxx14 | StandardCxx17); - } else if (std== "gnu++14" || std == "gnu++1y") { - flags |= CompilerFlags(StandardCxx14 | GnuExtensions); - flags &= ~CompilerFlags(StandardCxx11 | StandardCxx17); - } else if (std== "gnu++17" || std == "gnu++1z") { - flags |= CompilerFlags(StandardCxx17 | GnuExtensions); - flags &= ~CompilerFlags(StandardCxx11 | StandardCxx14); - } else if (std == "c89" || std == "c90" - || std == "iso9899:1990" || std == "iso9899:199409") { - flags &= ~CompilerFlags(StandardC99 | StandardC11); - } else if (std == "gnu89" || std == "gnu90") { - flags &= ~CompilerFlags(StandardC99 | StandardC11); - flags |= GnuExtensions; - } else if (std == "c99" || std == "c9x" - || std == "iso9899:1999" || std == "iso9899:199x") { - flags |= StandardC99; - flags &= ~StandardC11; - } else if (std == "gnu99" || std == "gnu9x") { - flags |= CompilerFlags(StandardC99 | GnuExtensions); - flags &= ~StandardC11; - } else if (std == "c11" || std == "c1x" || std == "iso9899:2011") { - flags |= CompilerFlags(StandardC99 | StandardC11); - } else if (std == "gnu11" || std == "gnu1x") { - flags |= CompilerFlags(StandardC99 | StandardC11 | GnuExtensions); - } + if (std.startsWith("gnu")) + flags |= CompilerFlags(GnuExtensions); + else + flags &= ~CompilerFlags(GnuExtensions); } else if (flag == "-fopenmp") { flags |= OpenMP; } else if (flag == "-fms-extensions") { flags |= MicrosoftExtensions; - } else if (flag == "-ansi") { - flags &= ~CompilerFlags(StandardCxx11 | GnuExtensions - | StandardC99 | StandardC11); } } @@ -1069,7 +1028,10 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const FileName &comp return result; tc->setLanguage(language); - tc->m_predefinedMacrosCache->insert(QStringList(), macros); + tc->m_predefinedMacrosCache + ->insert(QStringList(), + ToolChain::MacroInspectionReport{macros, + ToolChain::languageVersion(language, macros)}); tc->setCompilerCommand(compilerPath); tc->setSupportedAbis(detectedAbis.supportedAbis); tc->setTargetAbi(abi); @@ -1134,7 +1096,11 @@ void GccToolChainConfigWidget::applyImpl() tc->setDisplayName(displayName); // reset display name tc->setPlatformCodeGenFlags(splitString(m_platformCodeGenFlagsLineEdit->text())); tc->setPlatformLinkerFlags(splitString(m_platformLinkerFlagsLineEdit->text())); - tc->m_predefinedMacrosCache->insert(tc->platformCodeGenFlags(), m_macros); + tc->m_predefinedMacrosCache + ->insert(tc->platformCodeGenFlags(), + ToolChain::MacroInspectionReport{m_macros, + ToolChain::languageVersion(tc->language(), + m_macros)}); } void GccToolChainConfigWidget::setFromToolchain() @@ -1319,7 +1285,7 @@ void ClangToolChain::addToEnvironment(Environment &env) const ToolChain::CompilerFlags ClangToolChain::defaultCompilerFlags() const { - return CompilerFlags(GnuExtensions | StandardCxx11); + return CompilerFlags(GnuExtensions); } IOutputParser *ClangToolChain::outputParser() const diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h index 3458f63414..64e2acbe51 100644 --- a/src/plugins/projectexplorer/gcctoolchain.h +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -143,7 +143,7 @@ public: CompilerFlags compilerFlags(const QStringList &cxxflags) const override; WarningFlags warningFlags(const QStringList &cflags) const override; - PredefinedMacrosRunner createPredefinedMacrosRunner() const override; + MacroInspectionRunner createMacroInspectionRunner() const override; Macros predefinedMacros(const QStringList &cxxflags) const override; BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const override; @@ -253,7 +253,7 @@ private: mutable HeaderPaths m_headerPaths; mutable QString m_version; - mutable std::shared_ptr<Cache<QVector<Macro>, 64>> m_predefinedMacrosCache; + mutable std::shared_ptr<Cache<MacroInspectionReport, 64>> m_predefinedMacrosCache; mutable std::shared_ptr<Cache<HeaderPaths>> m_headerPathsCache; mutable ExtraHeaderPathsFunction m_extraHeaderPathsFunction = [](HeaderPaths &) {}; diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 765dc86d38..7fb74661ec 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -334,6 +334,7 @@ static QByteArray msvcCompilationFile() "__CLR_VER", "_CMMN_INTRIN_FUNC", "_CONTROL_FLOW_GUARD", + "__cplusplus", "__cplusplus_cli", "__cplusplus_winrt", "_CPPLIB_VER", diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index e0c1b113a8..e11481d06f 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -286,6 +286,79 @@ bool ToolChain::fromMap(const QVariantMap &data) return true; } +static long toLanguageVersionAsLong(QByteArray dateAsByteArray) +{ + dateAsByteArray.chop(1); // Strip 'L'. + return dateAsByteArray.toLong(nullptr); +} + +ToolChain::LanguageVersion ToolChain::cxxLanguageVersion(const QByteArray &cplusplusMacroValue) +{ + const long version = toLanguageVersionAsLong(cplusplusMacroValue); + + if (version > 201703L) + return LanguageVersion::LatestCxxVersion; + + switch (version) { + case 201703L: return LanguageVersion::CXX17; + case 201403L: Q_FALLTHROUGH(); + case 201402L: return LanguageVersion::CXX14; + case 201103L: return LanguageVersion::CXX11; + case 199711L: return LanguageVersion::CXX03; + default: + QTC_CHECK(false && "Unexpected __cplusplus value, assuming latest C++ we support."); + return LanguageVersion::LatestCxxVersion; + } +} + +ToolChain::LanguageVersion ToolChain::languageVersion(const Core::Id &language, const Macros ¯os) +{ + if (language == Constants::CXX_LANGUAGE_ID) { + for (const ProjectExplorer::Macro ¯o : macros) { + if (macro.key == "__cplusplus") // Check for the C++ identifying macro + return cxxLanguageVersion(macro.value); + } + + QTC_CHECK(false && "__cplusplus is not predefined, assuming latest C++ we support."); + return LanguageVersion::LatestCxxVersion; + } else if (language == Constants::C_LANGUAGE_ID) { + for (const ProjectExplorer::Macro ¯o : macros) { + if (macro.key == "__STDC_VERSION__") { + const long version = toLanguageVersionAsLong(macro.value); + + if (version > 201710L) + return LanguageVersion::LatestCVersion; + + switch (version) { + case 201710L: return LanguageVersion::C18; + case 201112L: return LanguageVersion::C11; + case 199901L: return LanguageVersion::C99; + case 199409L: return LanguageVersion::C89; // C89 as amended in 1994 + default: + QTC_CHECK(false && "Unexpected __STDC_VERSION__ value, " + "assuming latest C version we support."); + return LanguageVersion::LatestCVersion; + } + } + } + + // The __STDC_VERSION__ macro was introduced after C89. + // We haven't seen it, so it must be C89. + return LanguageVersion::C89; + } else { + QTC_CHECK(false && "Unexpected toolchain language, assuming latest C++ we support."); + return LanguageVersion::LatestCxxVersion; + } +} + +Q_GLOBAL_STATIC_WITH_ARGS(const QVector<QByteArray>, unwantedMacros, + ({"__cplusplus", "__STDC_VERSION__"})) + +bool ToolChain::isUnwantedMacro(const Macro ¯o) +{ + return unwantedMacros->contains(macro.key); +} + /*! Used by the tool chain kit information to validate the kit. */ diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index fcc7e93d06..89bbab09b4 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -109,26 +109,44 @@ public: enum CompilerFlag { NoFlags = 0, - StandardCxx11 = 0x1, - StandardC99 = 0x2, - StandardC11 = 0x4, GnuExtensions = 0x8, MicrosoftExtensions = 0x10, BorlandExtensions = 0x20, OpenMP = 0x40, ObjectiveC = 0x80, - StandardCxx14 = 0x100, - StandardCxx17 = 0x200, - StandardCxx98 = 0x400, }; + + // Keep in sync with ProjectPart::LanguageVersion! + enum LanguageVersion { + C89, + C99, + C11, + C18, + LatestCVersion = C18, + CXX98, + CXX03, + CXX11, + CXX14, + CXX17, + CXX2a, + LatestCxxVersion = CXX2a, + }; + Q_DECLARE_FLAGS(CompilerFlags, CompilerFlag) virtual CompilerFlags compilerFlags(const QStringList &cxxflags) const = 0; virtual WarningFlags warningFlags(const QStringList &cflags) const = 0; - // A PredefinedMacrosRunner is created in the ui thread and runs in another thread. - using PredefinedMacrosRunner = std::function<Macros(const QStringList &cxxflags)>; - virtual PredefinedMacrosRunner createPredefinedMacrosRunner() const = 0; + class MacroInspectionReport + { + public: + Macros macros; + LanguageVersion languageVersion; + }; + + // A MacroInspectionRunner is created in the ui thread and runs in another thread. + using MacroInspectionRunner = std::function<MacroInspectionReport(const QStringList &cxxflags)>; + virtual MacroInspectionRunner createMacroInspectionRunner() const = 0; virtual Macros predefinedMacros(const QStringList &cxxflags) const = 0; // A BuiltInHeaderPathsRunner is created in the ui thread and runs in another thread. @@ -157,6 +175,9 @@ public: virtual QList<Task> validateKit(const Kit *k) const; void setLanguage(Core::Id language); + static LanguageVersion cxxLanguageVersion(const QByteArray &cplusplusMacroValue); + static LanguageVersion languageVersion(const Core::Id &language, const Macros ¯os); + static bool isUnwantedMacro(const Macro ¯o); protected: explicit ToolChain(Core::Id typeId, Detection d); diff --git a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp index 409812440f..e0055bfe81 100644 --- a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp +++ b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp @@ -308,7 +308,7 @@ public: QString typeDisplayName() const override { return QString("Test Tool Chain"); } Abi targetAbi() const override { return Abi::hostAbi(); } bool isValid() const override { return m_valid; } - PredefinedMacrosRunner createPredefinedMacrosRunner() const override { return PredefinedMacrosRunner(); } + MacroInspectionRunner createMacroInspectionRunner() const override { return MacroInspectionRunner(); } Macros predefinedMacros(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags); return Macros(); } CompilerFlags compilerFlags(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags); return NoFlags; } WarningFlags warningFlags(const QStringList &cflags) const override { Q_UNUSED(cflags); return WarningFlags::NoWarnings; } diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp index 1e07625be3..7981547ab3 100644 --- a/src/plugins/qbsprojectmanager/qbsproject.cpp +++ b/src/plugins/qbsprojectmanager/qbsproject.cpp @@ -915,10 +915,8 @@ void QbsProject::updateCppCodeModel() CppTools::ProjectPart::QtVersion qtVersionFromKit = CppTools::ProjectPart::NoQt; if (qtVersion) { - if (qtVersion->qtVersion() <= QtSupport::QtVersionNumber(4,8,6)) - qtVersionFromKit = CppTools::ProjectPart::Qt4_8_6AndOlder; - else if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) - qtVersionFromKit = CppTools::ProjectPart::Qt4Latest; + if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) + qtVersionFromKit = CppTools::ProjectPart::Qt4; else qtVersionFromKit = CppTools::ProjectPart::Qt5; } diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index e825d600a2..2547797780 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -277,10 +277,8 @@ void QmakeProject::updateCppCodeModel() QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k); ProjectPart::QtVersion qtVersionForPart = ProjectPart::NoQt; if (qtVersion) { - if (qtVersion->qtVersion() <= QtSupport::QtVersionNumber(4,8,6)) - qtVersionForPart = ProjectPart::Qt4_8_6AndOlder; - else if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) - qtVersionForPart = ProjectPart::Qt4Latest; + if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0)) + qtVersionForPart = ProjectPart::Qt4; else qtVersionForPart = ProjectPart::Qt5; } diff --git a/tests/unit/mockup/projectexplorer/toolchain.h b/tests/unit/mockup/projectexplorer/toolchain.h index 93cb630c4c..3ce5ad8902 100644 --- a/tests/unit/mockup/projectexplorer/toolchain.h +++ b/tests/unit/mockup/projectexplorer/toolchain.h @@ -41,17 +41,11 @@ public: enum CompilerFlag { NoFlags = 0, - StandardCxx11 = 0x1, - StandardC99 = 0x2, - StandardC11 = 0x4, GnuExtensions = 0x8, MicrosoftExtensions = 0x10, BorlandExtensions = 0x20, OpenMP = 0x40, ObjectiveC = 0x80, - StandardCxx14 = 0x100, - StandardCxx17 = 0x200, - StandardCxx98 = 0x400, }; Q_DECLARE_FLAGS(CompilerFlags, CompilerFlag) @@ -60,8 +54,29 @@ public: using BuiltInHeaderPathsRunner = std::function<HeaderPaths(const QStringList &cxxflags, const QString &sysRoot)>; virtual BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const { return BuiltInHeaderPathsRunner(); } - using PredefinedMacrosRunner = std::function<Macros(const QStringList &cxxflags)>; - virtual PredefinedMacrosRunner createPredefinedMacrosRunner() const { return PredefinedMacrosRunner(); } + enum LanguageVersion { + C89, + C99, + C11, + C18, + LatestCVersion = C18, + CXX98, + CXX03, + CXX11, + CXX14, + CXX17, + CXX2a, + LatestCxxVersion = CXX2a, + }; + + class MacroInspectionReport + { + public: + Macros macros; + LanguageVersion languageVersion; // Derived from macros. + }; + using MacroInspectionRunner = std::function<MacroInspectionReport(const QStringList &cxxflags)>; + virtual MacroInspectionRunner createMacroInspectionRunner() const = 0; virtual QString originalTargetTriple() const { return QString(); } virtual QStringList extraCodeModelFlags() const { return QStringList(); } diff --git a/tests/unit/unittest/cppprojectinfogenerator-test.cpp b/tests/unit/unittest/cppprojectinfogenerator-test.cpp index 9a991a7520..b93ab46a73 100644 --- a/tests/unit/unittest/cppprojectinfogenerator-test.cpp +++ b/tests/unit/unittest/cppprojectinfogenerator-test.cpp @@ -39,6 +39,7 @@ using CppTools::ProjectUpdateInfo; using CppTools::ProjectPart; using CppTools::RawProjectPart; +using ProjectExplorer::Macros; using ProjectExplorer::ToolChain; using testing::Eq; @@ -65,6 +66,7 @@ protected: ProjectInfo generate(); protected: + ProjectUpdateInfo projectUpdateInfo; RawProjectPart rawProjectPart; }; @@ -115,19 +117,21 @@ TEST_F(ProjectInfoGenerator, ProjectPartHasLatestLanguageVersionByDefault) ASSERT_THAT(projectPart.languageVersion, Eq(ProjectPart::LatestCxxVersion)); } -TEST_F(ProjectInfoGenerator, UseCompilerFlagsForLanguageVersion) +TEST_F(ProjectInfoGenerator, UseMacroInspectionReportForLanguageVersion) { + projectUpdateInfo.cxxToolChainInfo.macroInspectionRunner = [](const QStringList &) { + return ToolChain::MacroInspectionReport{Macros(), ToolChain::LanguageVersion::CXX17}; + }; rawProjectPart.files = QStringList{ "foo.cpp" }; - rawProjectPart.flagsForCxx.compilerFlags = ToolChain::CompilerFlag::StandardCxx98; const ProjectInfo projectInfo = generate(); ASSERT_THAT(projectInfo.projectParts().size(), Eq(1)); const ProjectPart &projectPart = *projectInfo.projectParts().at(0); - ASSERT_THAT(projectPart.languageVersion, Eq(ProjectPart::CXX98)); + ASSERT_THAT(projectPart.languageVersion, Eq(ProjectPart::CXX17)); } -TEST_F(ProjectInfoGenerator, UseCompilerFlagsForLangaugeExtensions) +TEST_F(ProjectInfoGenerator, UseCompilerFlagsForLanguageExtensions) { rawProjectPart.files = QStringList{ "foo.cpp" }; rawProjectPart.flagsForCxx.compilerFlags = ToolChain::CompilerFlag::MicrosoftExtensions; @@ -160,7 +164,7 @@ void ProjectInfoGenerator::SetUp() ProjectInfo ProjectInfoGenerator::generate() { QFutureInterface<void> fi; - ProjectUpdateInfo projectUpdateInfo; + projectUpdateInfo.rawProjectParts += rawProjectPart; ::ProjectInfoGenerator generator(fi, projectUpdateInfo); |