Clang: Always force the built-in includes order

C++ includes must always come first, then clang resource
directory and then everything else.
This prevents both c++ standard headers and intrinsics issues.

Change-Id: Ia21bfa2fe99884c9adf58f7ef6beba1bede1724b
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Ivan Donchevskii
2018-12-05 10:36:24 +01:00
parent 867befc5ae
commit aa70799795
2 changed files with 94 additions and 83 deletions

View File

@@ -221,39 +221,43 @@ static QString clangIncludeDirectory(const QString &clangVersion,
#endif #endif
} }
static int lastIncludeIndex(const QStringList &options, const QRegularExpression &includePathRegEx) static QStringList insertResourceDirectory(const QStringList &options,
{ const QString &resourceDir,
int index = options.lastIndexOf(includePathRegEx); bool isMacOs = false)
while (index > 0 && options[index - 1] != "-I" && options[index - 1] != "-isystem")
index = options.lastIndexOf(includePathRegEx, index - 1);
if (index == 0)
index = -1;
return index;
}
static int includeIndexForResourceDirectory(const QStringList &options, bool isMacOs = false)
{ {
// include/c++, include/g++, libc++\include and libc++abi\include // include/c++, include/g++, libc++\include and libc++abi\include
static const QString cppIncludes = R"((.*[\/\\]include[\/\\].*(g\+\+|c\+\+).*))" static const QString cppIncludes = R"((.*[\/\\]include[\/\\].*(g\+\+|c\+\+).*))"
R"(|(.*libc\+\+[\/\\]include))" R"(|(.*libc\+\+[\/\\]include))"
R"(|(.*libc\+\+abi[\/\\]include))"; R"(|(.*libc\+\+abi[\/\\]include))";
static const QRegularExpression includeRegExp("\\A(" + cppIncludes + ")\\z");
// The same as includeRegExp but also matches /usr/local/include QStringList optionsBeforeResourceDirectory;
static const QRegularExpression includeRegExpMac( QStringList optionsAfterResourceDirectory;
"\\A(" + cppIncludes + R"(|([\/\\]usr[\/\\]local[\/\\]include))" + ")\\z"); QRegularExpression includeRegExp;
if (!isMacOs) {
includeRegExp = QRegularExpression("\\A(" + cppIncludes + ")\\z");
} else {
// The same as includeRegExp but also matches /usr/local/include
includeRegExp = QRegularExpression(
"\\A(" + cppIncludes + R"(|([\/\\]usr[\/\\]local[\/\\]include))" + ")\\z");
}
const int cppIncludeIndex = lastIncludeIndex(options, isMacOs for (const QString &option : options) {
? includeRegExpMac if (option == "-isystem")
: includeRegExp); continue;
if (cppIncludeIndex > 0) if (includeRegExp.match(option).hasMatch()) {
return cppIncludeIndex + 1; optionsBeforeResourceDirectory.push_back("-isystem");
optionsBeforeResourceDirectory.push_back(option);
} else {
optionsAfterResourceDirectory.push_back("-isystem");
optionsAfterResourceDirectory.push_back(option);
}
}
return -1; optionsBeforeResourceDirectory.push_back("-isystem");
optionsBeforeResourceDirectory.push_back(resourceDir);
return optionsBeforeResourceDirectory + optionsAfterResourceDirectory;
} }
void CompilerOptionsBuilder::insertWrappedQtHeaders() void CompilerOptionsBuilder::insertWrappedQtHeaders()
@@ -325,16 +329,11 @@ void CompilerOptionsBuilder::addHeaderPathOptions()
const QString clangIncludePath const QString clangIncludePath
= clangIncludeDirectory(m_clangVersion, m_clangResourceDirectory); = clangIncludeDirectory(m_clangVersion, m_clangResourceDirectory);
int includeIndexForResourceDir = includeIndexForResourceDirectory(
builtInIncludes, m_projectPart.toolChainTargetTriple.contains("darwin"));
if (includeIndexForResourceDir >= 0) { builtInIncludes = insertResourceDirectory(builtInIncludes,
builtInIncludes.insert(includeIndexForResourceDir, clangIncludePath); clangIncludePath,
builtInIncludes.insert(includeIndexForResourceDir, "-isystem"); m_projectPart.toolChainTargetTriple.contains(
} else { "darwin"));
builtInIncludes.prepend(clangIncludePath);
builtInIncludes.prepend("-isystem");
}
} }
m_options.append(builtInIncludes); m_options.append(builtInIncludes);

View File

@@ -231,50 +231,16 @@ TEST_F(CompilerOptionsBuilder, ClangHeadersAndCppIncludesPathsOrderLinux)
} }
TEST_F(CompilerOptionsBuilder, ClangHeadersAndCppIncludesPathsOrderNoVersion) TEST_F(CompilerOptionsBuilder, ClangHeadersAndCppIncludesPathsOrderNoVersion)
{
projectPart.headerPaths = {HeaderPath{"C:\\Qt\\Tools\\mingw530_32\\i686-w64-mingw32\\include", HeaderPathType::BuiltIn},
HeaderPath{"C:\\Qt\\Tools\\mingw530_32\\i686-w64-mingw32\\include\\c++", HeaderPathType::BuiltIn},
HeaderPath{"C:\\Qt\\Tools\\mingw530_32\\i686-w64-mingw32\\include\\c++\\i686-w64-mingw32", HeaderPathType::BuiltIn},
HeaderPath{"C:\\Qt\\Tools\\mingw530_32\\i686-w64-mingw32\\include\\c++\\backward", HeaderPathType::BuiltIn}
};
projectPart.toolChainTargetTriple = "x86_64-w64-windows-gnu";
CppTools::CompilerOptionsBuilder compilerOptionsBuilder(projectPart,
CppTools::UseSystemHeader::No,
CppTools::SkipBuiltIn::No,
CppTools::SkipLanguageDefines::Yes,
"7.0.0",
"");
compilerOptionsBuilder.addHeaderPathOptions();
ASSERT_THAT(compilerOptionsBuilder.options(),
ElementsAre("-nostdinc",
"-nostdlibinc",
"-isystem", QDir::toNativeSeparators("C:\\Qt\\Tools\\mingw530_32\\i686-w64-mingw32\\include"),
"-isystem", QDir::toNativeSeparators("C:\\Qt\\Tools\\mingw530_32\\i686-w64-mingw32\\include\\c++"),
"-isystem", QDir::toNativeSeparators("C:\\Qt\\Tools\\mingw530_32\\i686-w64-mingw32\\include\\c++\\i686-w64-mingw32"),
"-isystem", QDir::toNativeSeparators("C:\\Qt\\Tools\\mingw530_32\\i686-w64-mingw32\\include\\c++\\backward"),
"-isystem", QDir::toNativeSeparators(CLANG_RESOURCE_DIR "")));
}
TEST_F(CompilerOptionsBuilder, ClangHeadersAndCppIncludesPathsOrderAndroidClang)
{ {
projectPart.headerPaths = { projectPart.headerPaths = {
HeaderPath{ HeaderPath{"C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include", HeaderPathType::BuiltIn},
"C:\\Users\\test\\AppData\\Local\\Android\\sdk\\ndk-bundle\\sysroot\\usr\\include\\i686-linux-android", HeaderPath{"C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++",
HeaderPathType::BuiltIn}, HeaderPathType::BuiltIn},
HeaderPath{ HeaderPath{"C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++/i686-w64-mingw32",
"C:\\Users\\test\\AppData\\Local\\Android\\sdk\\ndk-bundle\\sources\\cxx-stl\\llvm-libc++\\include", HeaderPathType::BuiltIn},
HeaderPathType::BuiltIn}, HeaderPath{"C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++/backward",
HeaderPath{
"C:\\Users\\test\\AppData\\Local\\Android\\sdk\\ndk-bundle\\sources\\android\\support\\include",
HeaderPathType::BuiltIn},
HeaderPath{
"C:\\Users\\test\\AppData\\Local\\Android\\sdk\\ndk-bundle\\sources\\cxx-stl\\llvm-libc++abi\\include",
HeaderPathType::BuiltIn},
HeaderPath{"C:\\Users\\test\\AppData\\Local\\Android\\sdk\\ndk-bundle\\sysroot\\usr\\include",
HeaderPathType::BuiltIn}}; HeaderPathType::BuiltIn}};
projectPart.toolChainTargetTriple = "i686-linux-android"; projectPart.toolChainTargetTriple = "x86_64-w64-windows-gnu";
CppTools::CompilerOptionsBuilder compilerOptionsBuilder(projectPart, CppTools::CompilerOptionsBuilder compilerOptionsBuilder(projectPart,
CppTools::UseSystemHeader::No, CppTools::UseSystemHeader::No,
CppTools::SkipBuiltIn::No, CppTools::SkipBuiltIn::No,
@@ -290,22 +256,68 @@ TEST_F(CompilerOptionsBuilder, ClangHeadersAndCppIncludesPathsOrderAndroidClang)
"-nostdinc", "-nostdinc",
"-nostdlibinc", "-nostdlibinc",
"-isystem", "-isystem",
QDir::toNativeSeparators( QDir::toNativeSeparators("C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++"),
"C:\\Users\\test\\AppData\\Local\\Android\\sdk\\ndk-bundle\\sysroot\\usr\\include\\i686-linux-android"),
"-isystem", "-isystem",
QDir::toNativeSeparators( QDir::toNativeSeparators(
"C:\\Users\\test\\AppData\\Local\\Android\\sdk\\ndk-bundle\\sources\\cxx-stl\\llvm-libc++\\include"), "C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++/i686-w64-mingw32"),
"-isystem", "-isystem",
QDir::toNativeSeparators( QDir::toNativeSeparators(
"C:\\Users\\test\\AppData\\Local\\Android\\sdk\\ndk-bundle\\sources\\android\\support\\include"), "C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include/c++/backward"),
"-isystem",
QDir::toNativeSeparators(
"C:\\Users\\test\\AppData\\Local\\Android\\sdk\\ndk-bundle\\sources\\cxx-stl\\llvm-libc++abi\\include"),
"-isystem", "-isystem",
QDir::toNativeSeparators(CLANG_RESOURCE_DIR ""), QDir::toNativeSeparators(CLANG_RESOURCE_DIR ""),
"-isystem", "-isystem",
QDir::toNativeSeparators( QDir::toNativeSeparators("C:/Qt/Tools/mingw530_32/i686-w64-mingw32/include")));
"C:\\Users\\test\\AppData\\Local\\Android\\sdk\\ndk-bundle\\sysroot\\usr\\include"))); }
TEST_F(CompilerOptionsBuilder, ClangHeadersAndCppIncludesPathsOrderAndroidClang)
{
projectPart.headerPaths
= {HeaderPath{"C:/Users/test/AppData/Local/Android/sdk/ndk-"
"bundle/sysroot/usr/include/i686-linux-android",
HeaderPathType::BuiltIn},
HeaderPath{"C:/Users/test/AppData/Local/Android/sdk/ndk-bundle/sources/cxx-"
"stl/llvm-libc++/include",
HeaderPathType::BuiltIn},
HeaderPath{"C:/Users/test/AppData/Local/Android/sdk/ndk-"
"bundle/sources/android/support/include",
HeaderPathType::BuiltIn},
HeaderPath{"C:/Users/test/AppData/Local/Android/sdk/ndk-bundle/sources/cxx-"
"stl/llvm-libc++abi/include",
HeaderPathType::BuiltIn},
HeaderPath{
"C:/Users/test/AppData/Local/Android/sdk/ndk-bundle/sysroot/usr/include",
HeaderPathType::BuiltIn}};
projectPart.toolChainTargetTriple = "i686-linux-android";
CppTools::CompilerOptionsBuilder compilerOptionsBuilder(projectPart,
CppTools::UseSystemHeader::No,
CppTools::SkipBuiltIn::No,
CppTools::SkipLanguageDefines::Yes,
"7.0.0",
"");
compilerOptionsBuilder.addHeaderPathOptions();
ASSERT_THAT(
compilerOptionsBuilder.options(),
ElementsAre("-nostdinc",
"-nostdlibinc",
"-isystem",
QDir::toNativeSeparators("C:/Users/test/AppData/Local/Android/sdk/ndk-"
"bundle/sources/cxx-stl/llvm-libc++/include"),
"-isystem",
QDir::toNativeSeparators("C:/Users/test/AppData/Local/Android/sdk/ndk-"
"bundle/sources/cxx-stl/llvm-libc++abi/include"),
"-isystem",
QDir::toNativeSeparators(CLANG_RESOURCE_DIR ""),
"-isystem",
QDir::toNativeSeparators("C:/Users/test/AppData/Local/Android/sdk/ndk-"
"bundle/sysroot/usr/include/i686-linux-android"),
"-isystem",
QDir::toNativeSeparators("C:/Users/test/AppData/Local/Android/sdk/ndk-"
"bundle/sources/android/support/include"),
"-isystem",
QDir::toNativeSeparators("C:/Users/test/AppData/Local/Android/sdk/ndk-"
"bundle/sysroot/usr/include")));
} }
TEST_F(CompilerOptionsBuilder, NoPrecompiledHeader) TEST_F(CompilerOptionsBuilder, NoPrecompiledHeader)