summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@theqtcompany.com>2015-01-23 15:25:45 +0100
committerChristian Kandeler <christian.kandeler@theqtcompany.com>2015-01-30 15:38:40 +0200
commit0aa20dd26d641dcaeb19efc1028e408910032e93 (patch)
tree21615c28df840397dcd399c3f055c166e19dd51d
parent6aad65375b265bced5758cd147b89fe26ca5edff (diff)
downloadqt-creator-0aa20dd26d641dcaeb19efc1028e408910032e93.tar.gz
Add support for MSVC.
Via clang-cl, which supports the --analyze option now. Change-Id: Idbefe048eaa80e8c5bdb2244cb30c26ba7c71ef5 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
-rw-r--r--plugins/clangstaticanalyzer/ClangStaticAnalyzer.json.in1
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp49
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h2
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerruncontrolfactory.cpp3
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerrunner.cpp15
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerrunner.h1
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp7
-rw-r--r--plugins/clangstaticanalyzer/clangstaticanalyzerutils.h2
8 files changed, 56 insertions, 24 deletions
diff --git a/plugins/clangstaticanalyzer/ClangStaticAnalyzer.json.in b/plugins/clangstaticanalyzer/ClangStaticAnalyzer.json.in
index 13c2aa5b82..77cc31b40d 100644
--- a/plugins/clangstaticanalyzer/ClangStaticAnalyzer.json.in
+++ b/plugins/clangstaticanalyzer/ClangStaticAnalyzer.json.in
@@ -3,7 +3,6 @@
\"Version\" : \"$$QTCREATOR_VERSION\",
\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
\"Experimental\" : true,
- \"Platform\" : \"(Linux.*)|(OS X.*)\",
\"Vendor\" : \"Digia Plc\",
\"Copyright\" : \"(C) 2014 Digia Plc\",
\"License\" : [ \"Commercial Usage\",
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp
index 75757bc916..e027d24907 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.cpp
@@ -34,6 +34,7 @@
#include <cpptools/cppprojects.h>
#include <cpptools/cppprojectfile.h>
+#include <projectexplorer/kitinformation.h>
#include <projectexplorer/project.h>
#include <projectexplorer/target.h>
@@ -56,6 +57,8 @@ ClangStaticAnalyzerRunControl::ClangStaticAnalyzerRunControl(
const ProjectInfo &projectInfo)
: AnalyzerRunControl(startParams, runConfiguration)
, m_projectInfo(projectInfo)
+ , m_toolchainType(ProjectExplorer::ToolChainKitInformation
+ ::toolChain(runConfiguration->target()->kit())->type())
, m_initialFilesToProcessSize(0)
, m_filesAnalyzed(0)
, m_filesNotAnalyzed(0)
@@ -75,7 +78,7 @@ static QStringList tweakedArguments(const QString &filePath, const QStringList &
} else if (argument == QLatin1String("-o")) {
skip = true;
continue;
- } else if (argument == filePath) {
+ } else if (QDir::fromNativeSeparators(argument) == filePath) {
continue; // TODO: Let it in?
}
@@ -87,19 +90,30 @@ static QStringList tweakedArguments(const QString &filePath, const QStringList &
}
static QStringList argumentsFromProjectPart(const CppTools::ProjectPart::Ptr &projectPart,
- CppTools::ProjectFile::Kind fileKind)
+ CppTools::ProjectFile::Kind fileKind,
+ const QString &toolchainType)
{
QStringList result;
const bool objcExt = projectPart->languageExtensions & ProjectPart::ObjectiveCExtensions;
- result += CppTools::CompilerOptionsBuilder::createLanguageOption(fileKind, objcExt);
+ result += CppTools::CompilerOptionsBuilder::createLanguageOption(fileKind, objcExt,
+ toolchainType);
result += CppTools::CompilerOptionsBuilder::createOptionsForLanguage(
projectPart->languageVersion,
- projectPart->languageExtensions);
- result += CppTools::CompilerOptionsBuilder::createDefineOptions(projectPart->toolchainDefines);
- result += CppTools::CompilerOptionsBuilder::createDefineOptions(projectPart->projectDefines);
- result += CppTools::CompilerOptionsBuilder::createHeaderPathOptions(projectPart->headerPaths);
- result += QLatin1String("-fPIC"); // TODO: Remove?
+ projectPart->languageExtensions, false,
+ toolchainType);
+ result += CppTools::CompilerOptionsBuilder::createDefineOptions(projectPart->toolchainDefines,
+ false, toolchainType);
+ result += CppTools::CompilerOptionsBuilder::createDefineOptions(projectPart->projectDefines,
+ false, toolchainType);
+ result += CppTools::CompilerOptionsBuilder::createHeaderPathOptions(
+ projectPart->headerPaths,
+ CompilerOptionsBuilder::IsBlackListed(),
+ toolchainType);
+ if (toolchainType == QLatin1String("msvc"))
+ result += QLatin1String("/EHsc"); // clang-cl does not understand exceptions
+ else
+ result += QLatin1String("-fPIC"); // TODO: Remove?
return result;
}
@@ -127,7 +141,7 @@ static QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyzeFromCompi
}
static QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyzeFromProjectParts(
- const QList<ProjectPart::Ptr> projectParts)
+ const QList<ProjectPart::Ptr> projectParts, const QString &toolchainType)
{
typedef ClangStaticAnalyzerRunControl::AnalyzeUnit AnalyzeUnit;
qCDebug(LOG) << "Taking arguments for analyzing from ProjectParts.";
@@ -143,7 +157,8 @@ static QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyzeFromProje
continue;
QTC_CHECK(file.kind != ProjectFile::Unclassified);
if (ProjectFile::isSource(file.kind)) {
- const QStringList arguments = argumentsFromProjectPart(projectPart, file.kind);
+ const QStringList arguments
+ = argumentsFromProjectPart(projectPart, file.kind, toolchainType);
unitsToAnalyze << AnalyzeUnit(file.path, arguments);
}
}
@@ -152,15 +167,14 @@ static QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyzeFromProje
return unitsToAnalyze;
}
-static QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyze(
- const CppTools::ProjectInfo &projectInfo)
+QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> ClangStaticAnalyzerRunControl::unitsToAnalyze()
{
- QTC_ASSERT(projectInfo.isValid(), return QList<ClangStaticAnalyzerRunControl::AnalyzeUnit>());
+ QTC_ASSERT(m_projectInfo.isValid(), return QList<ClangStaticAnalyzerRunControl::AnalyzeUnit>());
- const ProjectInfo::CompilerCallData compilerCallData = projectInfo.compilerCallData();
+ const ProjectInfo::CompilerCallData compilerCallData = m_projectInfo.compilerCallData();
if (!compilerCallData.isEmpty())
return unitsToAnalyzeFromCompilerCallData(compilerCallData);
- return unitsToAnalyzeFromProjectParts(projectInfo.projectParts());
+ return unitsToAnalyzeFromProjectParts(m_projectInfo.projectParts(), m_toolchainType);
}
bool ClangStaticAnalyzerRunControl::startEngine()
@@ -174,7 +188,8 @@ bool ClangStaticAnalyzerRunControl::startEngine()
// Check clang executable
bool isValidClangExecutable;
- const QString executable = clangExecutableFromSettings(&isValidClangExecutable);
+ const QString executable
+ = clangExecutableFromSettings(m_toolchainType, &isValidClangExecutable);
if (!isValidClangExecutable) {
emit appendMessage(tr("Clang Static Analyzer: Invalid executable \"%1\", stop.")
.arg(executable) + QLatin1Char('\n'),
@@ -196,7 +211,7 @@ bool ClangStaticAnalyzerRunControl::startEngine()
m_clangLogFileDir = temporaryDir.path();
// Collect files
- QList<AnalyzeUnit> unitsToProcess = unitsToAnalyze(m_projectInfo);
+ QList<AnalyzeUnit> unitsToProcess = unitsToAnalyze();
Utils::sort(unitsToProcess, [](const AnalyzeUnit &a1, const AnalyzeUnit &a2) -> bool {
return a1.file < a2.file;
});
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h b/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h
index cc56f107f6..b47b6c8bab 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrol.h
@@ -56,6 +56,7 @@ signals:
void newDiagnosticsAvailable(const QList<Diagnostic> &diagnostics);
private:
+ QList<ClangStaticAnalyzerRunControl::AnalyzeUnit> unitsToAnalyze();
void analyzeNextFile();
ClangStaticAnalyzerRunner *createRunner();
@@ -68,6 +69,7 @@ private:
private:
const CppTools::ProjectInfo m_projectInfo;
+ const QString m_toolchainType;
QString m_clangExecutable;
QString m_clangLogFileDir;
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrolfactory.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrolfactory.cpp
index 301496fac7..bf6f5d43da 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrolfactory.cpp
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerruncontrolfactory.cpp
@@ -61,7 +61,8 @@ bool ClangStaticAnalyzerRunControlFactory::canRun(RunConfiguration *runConfigura
QTC_ASSERT(kit, return false);
ToolChain *toolChain = ToolChainKitInformation::toolChain(kit);
return toolChain && (toolChain->type() == QLatin1String("clang")
- || toolChain->type() == QLatin1String("gcc"));
+ || toolChain->type() == QLatin1String("gcc")
+ || toolChain->type() == QLatin1String("msvc"));
}
RunControl *ClangStaticAnalyzerRunControlFactory::create(RunConfiguration *runConfiguration,
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerrunner.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerrunner.cpp
index 5c469a07a2..d2cc637cc2 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerrunner.cpp
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerrunner.cpp
@@ -50,7 +50,7 @@ static QStringList constructCommandLineArguments(const QString &filePath,
<< logFile
;
arguments += options;
- arguments << filePath;
+ arguments << QDir::toNativeSeparators(filePath);
return arguments;
}
@@ -73,6 +73,7 @@ ClangStaticAnalyzerRunner::ClangStaticAnalyzerRunner(const QString &clangExecuta
QTC_CHECK(!m_clangLogFileDir.isEmpty());
m_process.setProcessChannelMode(QProcess::MergedChannels);
+ m_process.setWorkingDirectory(m_clangLogFileDir); // Current clang-cl puts log file into working dir.
connect(&m_process, &QProcess::started,
this, &ClangStaticAnalyzerRunner::onProcessStarted);
connect(&m_process, static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
@@ -122,7 +123,7 @@ void ClangStaticAnalyzerRunner::onProcessFinished(int exitCode, QProcess::ExitSt
{
if (exitStatus == QProcess::NormalExit) {
if (exitCode == 0)
- emit finishedWithSuccess(m_logFile);
+ emit finishedWithSuccess(actualLogFile());
else
emit finishedWithFailure(finishedWithBadExitCode(exitCode), processCommandlineAndOutput());
} else { // == QProcess::CrashExit
@@ -169,5 +170,15 @@ QString ClangStaticAnalyzerRunner::processCommandlineAndOutput() const
QString::fromLocal8Bit(m_processOutput));
}
+QString ClangStaticAnalyzerRunner::actualLogFile() const
+{
+ if (QFileInfo(m_logFile).size() == 0) {
+ // Current clang-cl ignores -o, always putting the log file into the working directory.
+ return m_clangLogFileDir + QLatin1Char('/') + QFileInfo(m_filePath).completeBaseName()
+ + QLatin1String(".plist");
+ }
+ return m_logFile;
+}
+
} // namespace Internal
} // namespace ClangStaticAnalyzer
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerrunner.h b/plugins/clangstaticanalyzer/clangstaticanalyzerrunner.h
index 461f694e2e..b175ef8b3f 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerrunner.h
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerrunner.h
@@ -60,6 +60,7 @@ private:
QString createLogFile(const QString &filePath) const;
QString processCommandlineAndOutput() const;
+ QString actualLogFile() const;
private:
QString m_clangExecutable;
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp
index 6beff9e192..e349ebe8c5 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerutils.cpp
@@ -37,9 +37,12 @@ static bool isFileExecutable(const QString &executablePath)
namespace ClangStaticAnalyzer {
namespace Internal {
-QString clangExecutableFromSettings(bool *isValid)
+QString clangExecutableFromSettings(const QString &toolchainType, bool *isValid)
{
- return clangExecutable(ClangStaticAnalyzerSettings::instance()->clangExecutable(), isValid);
+ QString exeFromSettings = ClangStaticAnalyzerSettings::instance()->clangExecutable();
+ if (toolchainType == QLatin1String("msvc"))
+ exeFromSettings.replace(QLatin1String("clang.exe"), QLatin1String("clang-cl.exe"));
+ return clangExecutable(exeFromSettings, isValid);
}
QString clangExecutable(const QString &fileNameOrPath, bool *isValid)
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h b/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h
index 8c63470022..0c7a49b18d 100644
--- a/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h
+++ b/plugins/clangstaticanalyzer/clangstaticanalyzerutils.h
@@ -33,7 +33,7 @@ namespace Internal {
class Location;
QString clangExecutable(const QString &fileNameOrPath, bool *isValid);
-QString clangExecutableFromSettings(bool *isValid);
+QString clangExecutableFromSettings(const QString &toolchainType, bool *isValid);
QString createFullLocationString(const ClangStaticAnalyzer::Internal::Location &location);