summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools/compileroptionsbuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/cpptools/compileroptionsbuilder.cpp')
-rw-r--r--src/plugins/cpptools/compileroptionsbuilder.cpp163
1 files changed, 128 insertions, 35 deletions
diff --git a/src/plugins/cpptools/compileroptionsbuilder.cpp b/src/plugins/cpptools/compileroptionsbuilder.cpp
index 43a4146218..8164009bf1 100644
--- a/src/plugins/cpptools/compileroptionsbuilder.cpp
+++ b/src/plugins/cpptools/compileroptionsbuilder.cpp
@@ -25,7 +25,11 @@
#include "compileroptionsbuilder.h"
+#include <coreplugin/icore.h>
+
#include <projectexplorer/projectexplorerconstants.h>
+
+#include <utils/qtcassert.h>
#include <utils/qtcfallthrough.h>
#include <QDir>
@@ -33,9 +37,40 @@
namespace CppTools {
-CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart)
+CompilerOptionsBuilder::CompilerOptionsBuilder(const ProjectPart &projectPart,
+ const QString &clangVersion,
+ const QString &clangResourceDirectory)
: m_projectPart(projectPart)
+ , m_clangVersion(clangVersion)
+ , m_clangResourceDirectory(clangResourceDirectory)
+{
+}
+
+QStringList CompilerOptionsBuilder::build(CppTools::ProjectFile::Kind fileKind, PchUsage pchUsage)
{
+ m_options.clear();
+
+ addWordWidth();
+ addTargetTriple();
+ addLanguageOption(fileKind);
+ addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
+ enableExceptions();
+
+ addToolchainAndProjectMacros();
+ undefineClangVersionMacrosForMsvc();
+ undefineCppLanguageFeatureMacrosForMsvc2015();
+ addDefineFunctionMacrosMsvc();
+
+ addPredefinedHeaderPathsOptions();
+ addPrecompiledHeaderOptions(pchUsage);
+ addHeaderPathOptions();
+ addProjectConfigFileInclude();
+
+ addMsvcCompatibilityVersion();
+
+ addExtraOptions();
+
+ return options();
}
QStringList CompilerOptionsBuilder::options() const
@@ -101,7 +136,8 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
break;
}
- result.append(prefix + QDir::toNativeSeparators(headerPath.path));
+ result.append(prefix);
+ result.append(QDir::toNativeSeparators(headerPath.path));
}
m_options.append(result);
@@ -237,15 +273,13 @@ void CompilerOptionsBuilder::addOptionsForLanguage(bool checkForBorlandExtension
opts << (gnuExtensions ? QLatin1String("-std=gnu++98") : QLatin1String("-std=c++98"));
break;
case ProjectPart::CXX03:
- // Clang 3.6 does not know -std=gnu++03.
- opts << QLatin1String("-std=c++03");
+ opts << (gnuExtensions ? QLatin1String("-std=gnu++03") : QLatin1String("-std=c++03"));
break;
case ProjectPart::CXX14:
opts << (gnuExtensions ? QLatin1String("-std=gnu++14") : QLatin1String("-std=c++14"));
break;
case ProjectPart::CXX17:
- // TODO: Change to (probably) "gnu++17"/"c++17" at some point in the future.
- opts << (gnuExtensions ? QLatin1String("-std=gnu++1z") : QLatin1String("-std=c++1z"));
+ opts << (gnuExtensions ? QLatin1String("-std=gnu++17") : QLatin1String("-std=c++17"));
break;
}
@@ -292,24 +326,39 @@ void CompilerOptionsBuilder::addMsvcCompatibilityVersion()
static QStringList languageFeatureMacros()
{
// CLANG-UPGRADE-CHECK: Update known language features macros.
- // Collected with:
- // $ CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
- // $ D:\usr\llvm-3.8.0\bin\clang++.exe -fms-compatibility-version=19 -std=c++1y -dM -E D:\empty.cpp | grep __cpp_
+ // Collected with the following command line.
+ // * Use latest -fms-compatibility-version and -std possible.
+ // * Compatibility version 19 vs 1910 did not matter.
+ // $ clang++ -fms-compatibility-version=19 -std=c++1z -dM -E D:\empty.cpp | grep __cpp_
static QStringList macros{
+ QLatin1String("__cpp_aggregate_bases"),
QLatin1String("__cpp_aggregate_nsdmi"),
QLatin1String("__cpp_alias_templates"),
+ QLatin1String("__cpp_aligned_new"),
QLatin1String("__cpp_attributes"),
QLatin1String("__cpp_binary_literals"),
+ QLatin1String("__cpp_capture_star_this"),
QLatin1String("__cpp_constexpr"),
QLatin1String("__cpp_decltype"),
QLatin1String("__cpp_decltype_auto"),
+ QLatin1String("__cpp_deduction_guides"),
QLatin1String("__cpp_delegating_constructors"),
QLatin1String("__cpp_digit_separators"),
+ QLatin1String("__cpp_enumerator_attributes"),
+ QLatin1String("__cpp_exceptions"),
+ QLatin1String("__cpp_fold_expressions"),
QLatin1String("__cpp_generic_lambdas"),
+ QLatin1String("__cpp_hex_float"),
+ QLatin1String("__cpp_if_constexpr"),
QLatin1String("__cpp_inheriting_constructors"),
QLatin1String("__cpp_init_captures"),
QLatin1String("__cpp_initializer_lists"),
+ QLatin1String("__cpp_inline_variables"),
QLatin1String("__cpp_lambdas"),
+ QLatin1String("__cpp_namespace_attributes"),
+ QLatin1String("__cpp_nested_namespace_definitions"),
+ QLatin1String("__cpp_noexcept_function_type"),
+ QLatin1String("__cpp_nontype_template_args"),
QLatin1String("__cpp_nsdmi"),
QLatin1String("__cpp_range_based_for"),
QLatin1String("__cpp_raw_strings"),
@@ -318,11 +367,15 @@ static QStringList languageFeatureMacros()
QLatin1String("__cpp_rtti"),
QLatin1String("__cpp_rvalue_references"),
QLatin1String("__cpp_static_assert"),
+ QLatin1String("__cpp_structured_bindings"),
+ QLatin1String("__cpp_template_auto"),
+ QLatin1String("__cpp_threadsafe_static_init"),
QLatin1String("__cpp_unicode_characters"),
QLatin1String("__cpp_unicode_literals"),
QLatin1String("__cpp_user_defined_literals"),
QLatin1String("__cpp_variable_templates"),
QLatin1String("__cpp_variadic_templates"),
+ QLatin1String("__cpp_variadic_using"),
};
return macros;
@@ -332,8 +385,8 @@ void CompilerOptionsBuilder::undefineCppLanguageFeatureMacrosForMsvc2015()
{
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID
&& m_projectPart.isMsvc2015Toolchain) {
- // Undefine the language feature macros that are pre-defined in clang-cl 3.8.0,
- // but not in MSVC2015's cl.exe.
+ // Undefine the language feature macros that are pre-defined in clang-cl,
+ // but not in MSVC's cl.exe.
foreach (const QString &macroName, languageFeatureMacros())
m_options.append(undefineOption() + macroName);
}
@@ -345,17 +398,9 @@ void CompilerOptionsBuilder::addDefineFunctionMacrosMsvc()
addMacros({{"__FUNCSIG__", "\"\""}, {"__FUNCTION__", "\"\""}, {"__FUNCDNAME__", "\"\""}});
}
-void CompilerOptionsBuilder::addDefineFloat128ForMingw()
-{
- // CLANG-UPGRADE-CHECK: Workaround still needed?
- // https://llvm.org/bugs/show_bug.cgi?id=30685
- if (m_projectPart.toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID)
- addDefine({"__float128", "short", ProjectExplorer::MacroType::Define});
-}
-
QString CompilerOptionsBuilder::includeDirOption() const
{
- return QLatin1String("-I");
+ return QLatin1String("-isystem");
}
QByteArray CompilerOptionsBuilder::macroOption(const ProjectExplorer::Macro &macro) const
@@ -394,12 +439,6 @@ QString CompilerOptionsBuilder::includeOption() const
return QLatin1String("-include");
}
-static bool isGccOrMinGwToolchain(const Core::Id &toolchainType)
-{
- return toolchainType == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID
- || toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID;
-}
-
bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro &macro) const
{
// This is a quick fix for QTCREATORBUG-11501.
@@ -407,16 +446,10 @@ bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro
if (macro.key == "__cplusplus")
return true;
- // gcc 4.9 has:
- // #define __has_include(STR) __has_include__(STR)
- // #define __has_include_next(STR) __has_include_next__(STR)
- // The right-hand sides are gcc built-ins that clang does not understand, and they'd
- // override clang's own (non-macro, it seems) definitions of the symbols on the left-hand
- // side.
- if (isGccOrMinGwToolchain(m_projectPart.toolchainType)
- && macro.key.contains("has_include")) {
+ // 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"))
return true;
- }
// If _FORTIFY_SOURCE is defined (typically in release mode), it will
// enable the inclusion of extra headers to help catching buffer overflows
@@ -449,4 +482,64 @@ bool CompilerOptionsBuilder::excludeHeaderPath(const QString &headerPath) const
return clangIncludeDir.match(headerPath).hasMatch();
}
+void CompilerOptionsBuilder::addPredefinedHeaderPathsOptions()
+{
+ add("-nostdinc");
+ add("-nostdlibinc");
+
+ // In case of MSVC we need builtin clang defines to correctly handle clang includes
+ if (m_projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
+ add("-undef");
+
+ addClangIncludeFolder();
+}
+
+void CompilerOptionsBuilder::addClangIncludeFolder()
+{
+ QTC_CHECK(!m_clangVersion.isEmpty());
+ add(includeDirOption());
+ add(clangIncludeDirectory());
+}
+
+void CompilerOptionsBuilder::addProjectConfigFileInclude()
+{
+ if (!m_projectPart.projectConfigFile.isEmpty()) {
+ add("-include");
+ add(QDir::toNativeSeparators(m_projectPart.projectConfigFile));
+ }
+}
+
+static QString creatorLibexecPath()
+{
+#ifndef UNIT_TESTS
+ return Core::ICore::instance()->libexecPath();
+#else
+ return QString();
+#endif
+}
+
+QString CompilerOptionsBuilder::clangIncludeDirectory() const
+{
+ QDir dir(creatorLibexecPath() + "/clang" + clangIncludePath(m_clangVersion));
+ if (!dir.exists() || !QFileInfo(dir, "stdint.h").exists())
+ dir = QDir(m_clangResourceDirectory);
+ return QDir::toNativeSeparators(dir.canonicalPath());
+}
+
+void CompilerOptionsBuilder::undefineClangVersionMacrosForMsvc()
+{
+ if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
+ static QStringList macroNames {
+ "__clang__",
+ "__clang_major__",
+ "__clang_minor__",
+ "__clang_patchlevel__",
+ "__clang_version__"
+ };
+
+ foreach (const QString &macroName, macroNames)
+ add(undefineOption() + macroName);
+ }
+}
+
} // namespace CppTools