Clang: StaticAnalyzer: use the default compiler options builder

Analyzer has clang path and can generate necessary header paths
to be able to use default options builder.

Change-Id: I9bb1fc158f045f6e099817c5557ee7d9e38416fb
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
Ivan Donchevskii
2017-11-17 14:13:55 +01:00
parent 0269503dd8
commit 1601f53542
4 changed files with 43 additions and 45 deletions

View File

@@ -191,37 +191,9 @@ QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStri
return newArguments; return newArguments;
} }
class ClangStaticAnalyzerOptionsBuilder final : public CompilerOptionsBuilder
{
public:
ClangStaticAnalyzerOptionsBuilder(const CppTools::ProjectPart &projectPart)
: CompilerOptionsBuilder(projectPart)
{
}
bool excludeHeaderPath(const QString &headerPath) const final
{
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID
&& headerPath.contains(m_projectPart.toolChainTargetTriple)) {
return true;
}
return CompilerOptionsBuilder::excludeHeaderPath(headerPath);
}
void addPredefinedHeaderPathsOptions() final
{
add("-undef");
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
// exclude default clang path to use msvc includes
add("-nostdinc");
add("-nostdlibinc");
}
}
};
static QStringList createMsCompatibilityVersionOption(const ProjectPart &projectPart) static QStringList createMsCompatibilityVersionOption(const ProjectPart &projectPart)
{ {
ClangStaticAnalyzerOptionsBuilder optionsBuilder(projectPart); CompilerOptionsBuilder optionsBuilder(projectPart);
optionsBuilder.addMsvcCompatibilityVersion(); optionsBuilder.addMsvcCompatibilityVersion();
const QStringList option = optionsBuilder.options(); const QStringList option = optionsBuilder.options();
@@ -231,7 +203,7 @@ static QStringList createMsCompatibilityVersionOption(const ProjectPart &project
static QStringList createOptionsToUndefineCppLanguageFeatureMacrosForMsvc2015( static QStringList createOptionsToUndefineCppLanguageFeatureMacrosForMsvc2015(
const ProjectPart &projectPart) const ProjectPart &projectPart)
{ {
ClangStaticAnalyzerOptionsBuilder optionsBuilder(projectPart); CompilerOptionsBuilder optionsBuilder(projectPart);
optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015(); optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015();
return optionsBuilder.options(); return optionsBuilder.options();
@@ -239,7 +211,7 @@ static QStringList createOptionsToUndefineCppLanguageFeatureMacrosForMsvc2015(
static QStringList createOptionsToUndefineClangVersionMacrosForMsvc(const ProjectPart &projectPart) static QStringList createOptionsToUndefineClangVersionMacrosForMsvc(const ProjectPart &projectPart)
{ {
ClangStaticAnalyzerOptionsBuilder optionsBuilder(projectPart); CompilerOptionsBuilder optionsBuilder(projectPart);
optionsBuilder.undefineClangVersionMacrosForMsvc(); optionsBuilder.undefineClangVersionMacrosForMsvc();
return optionsBuilder.options(); return optionsBuilder.options();
@@ -251,7 +223,7 @@ static QStringList createHeaderPathsOptionsForClangOnMac(const ProjectPart &proj
if (Utils::HostOsInfo::isMacHost() if (Utils::HostOsInfo::isMacHost()
&& projectPart.toolchainType == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) { && projectPart.toolchainType == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) {
ClangStaticAnalyzerOptionsBuilder optionsBuilder(projectPart); CompilerOptionsBuilder optionsBuilder(projectPart);
optionsBuilder.addHeaderPathOptions(); optionsBuilder.addHeaderPathOptions();
options = optionsBuilder.options(); options = optionsBuilder.options();
} }
@@ -310,7 +282,9 @@ static AnalyzeUnits unitsToAnalyzeFromCompilerCallData(
return unitsToAnalyze; return unitsToAnalyze;
} }
static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Ptr> projectParts) static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Ptr> projectParts,
const QString &clangVersion,
const QString &clangResourceDirectory)
{ {
qCDebug(LOG) << "Taking arguments for analyzing from ProjectParts."; qCDebug(LOG) << "Taking arguments for analyzing from ProjectParts.";
@@ -327,8 +301,9 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Pt
QTC_CHECK(file.kind != ProjectFile::Unsupported); QTC_CHECK(file.kind != ProjectFile::Unsupported);
if (ProjectFile::isSource(file.kind)) { if (ProjectFile::isSource(file.kind)) {
const CompilerOptionsBuilder::PchUsage pchUsage = CppTools::getPchUsage(); const CompilerOptionsBuilder::PchUsage pchUsage = CppTools::getPchUsage();
const QStringList arguments CompilerOptionsBuilder optionsBuilder(*projectPart, clangVersion,
= ClangStaticAnalyzerOptionsBuilder(*projectPart).build(file.kind, pchUsage); clangResourceDirectory);
const QStringList arguments = optionsBuilder.build(file.kind, pchUsage);
unitsToAnalyze << AnalyzeUnit(file.path, arguments); unitsToAnalyze << AnalyzeUnit(file.path, arguments);
} }
} }
@@ -350,14 +325,23 @@ static QHash<QString, ProjectPart::Ptr> generateCallGroupToProjectPartMapping(
return mapping; return mapping;
} }
AnalyzeUnits ClangStaticAnalyzerToolRunner::sortedUnitsToAnalyze() static QString clangResourceDir(const QString &clangExecutable, const QString &clangVersion)
{
QDir llvmDir = QFileInfo(clangExecutable).dir();
llvmDir.cdUp();
return llvmDir.absolutePath() + clangIncludePath(clangVersion);
}
AnalyzeUnits ClangStaticAnalyzerToolRunner::sortedUnitsToAnalyze(const QString &clangVersion)
{ {
QTC_ASSERT(m_projectInfo.isValid(), return AnalyzeUnits()); QTC_ASSERT(m_projectInfo.isValid(), return AnalyzeUnits());
AnalyzeUnits units; AnalyzeUnits units;
const ProjectInfo::CompilerCallData compilerCallData = m_projectInfo.compilerCallData(); const ProjectInfo::CompilerCallData compilerCallData = m_projectInfo.compilerCallData();
if (compilerCallData.isEmpty()) { if (compilerCallData.isEmpty()) {
units = unitsToAnalyzeFromProjectParts(m_projectInfo.projectParts()); const QString clangResourceDirectory = clangResourceDir(m_clangExecutable, clangVersion);
units = unitsToAnalyzeFromProjectParts(m_projectInfo.projectParts(), clangVersion,
clangResourceDirectory);
} else { } else {
const QHash<QString, ProjectPart::Ptr> callGroupToProjectPart const QHash<QString, ProjectPart::Ptr> callGroupToProjectPart
= generateCallGroupToProjectPartMapping(m_projectInfo.projectParts()); = generateCallGroupToProjectPartMapping(m_projectInfo.projectParts());
@@ -480,7 +464,7 @@ void ClangStaticAnalyzerToolRunner::start()
m_clangLogFileDir = temporaryDir.path(); m_clangLogFileDir = temporaryDir.path();
// Collect files // Collect files
const AnalyzeUnits unitsToProcess = sortedUnitsToAnalyze(); const AnalyzeUnits unitsToProcess = sortedUnitsToAnalyze(version.toString());
qCDebug(LOG) << "Files to process:" << unitsToProcess; qCDebug(LOG) << "Files to process:" << unitsToProcess;
m_unitsToProcess = unitsToProcess; m_unitsToProcess = unitsToProcess;
m_initialFilesToProcessSize = m_unitsToProcess.count(); m_initialFilesToProcessSize = m_unitsToProcess.count();

View File

@@ -62,7 +62,7 @@ private:
void start() final; void start() final;
void stop() final; void stop() final;
AnalyzeUnits sortedUnitsToAnalyze(); AnalyzeUnits sortedUnitsToAnalyze(const QString &clangVersion);
void analyzeNextFile(); void analyzeNextFile();
ClangStaticAnalyzerRunner *createRunner(); ClangStaticAnalyzerRunner *createRunner();

View File

@@ -29,6 +29,7 @@
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h>
#include <utils/qtcfallthrough.h> #include <utils/qtcfallthrough.h>
#include <QDir> #include <QDir>
@@ -499,14 +500,20 @@ bool CompilerOptionsBuilder::excludeHeaderPath(const QString &headerPath) const
void CompilerOptionsBuilder::addPredefinedHeaderPathsOptions() void CompilerOptionsBuilder::addPredefinedHeaderPathsOptions()
{ {
add("-undef");
add("-nostdinc"); add("-nostdinc");
add("-nostdlibinc"); add("-nostdlibinc");
if (!m_clangVersion.isEmpty() // In case of MSVC we need builtin clang defines to correctly handle clang includes
&& m_projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) { if (m_projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
add(includeDirOption() + clangIncludeDirectory()); add("-undef");
addClangIncludeFolder();
} }
void CompilerOptionsBuilder::addClangIncludeFolder()
{
QTC_CHECK(!m_clangVersion.isEmpty());
add(includeDirOption() + clangIncludeDirectory());
} }
void CompilerOptionsBuilder::addProjectConfigFileInclude() void CompilerOptionsBuilder::addProjectConfigFileInclude()
@@ -528,7 +535,7 @@ static QString creatorLibexecPath()
QString CompilerOptionsBuilder::clangIncludeDirectory() const QString CompilerOptionsBuilder::clangIncludeDirectory() const
{ {
QDir dir(creatorLibexecPath() + "/clang/lib/clang/" + m_clangVersion + "/include"); QDir dir(creatorLibexecPath() + "/clang" + clangIncludePath(m_clangVersion));
if (!dir.exists() || !QFileInfo(dir, "stdint.h").exists()) if (!dir.exists() || !QFileInfo(dir, "stdint.h").exists())
dir = QDir(m_clangResourceDirectory); dir = QDir(m_clangResourceDirectory);
return QDir::toNativeSeparators(dir.canonicalPath()); return QDir::toNativeSeparators(dir.canonicalPath());

View File

@@ -90,10 +90,17 @@ private:
QByteArray toDefineOption(const ProjectExplorer::Macro &macro) const; QByteArray toDefineOption(const ProjectExplorer::Macro &macro) const;
QString defineDirectiveToDefineOption(const ProjectExplorer::Macro &marco) const; QString defineDirectiveToDefineOption(const ProjectExplorer::Macro &marco) const;
QString clangIncludeDirectory() const; QString clangIncludeDirectory() const;
void addClangIncludeFolder();
QStringList m_options; QStringList m_options;
QString m_clangVersion; QString m_clangVersion;
QString m_clangResourceDirectory; QString m_clangResourceDirectory;
}; };
template<class T>
T clangIncludePath(const T &clangVersion)
{
return "/lib/clang/" + clangVersion + "/include";
}
} // namespace CppTools } // namespace CppTools