diff options
author | Christian Kandeler <christian.kandeler@theqtcompany.com> | 2015-01-23 15:25:45 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@theqtcompany.com> | 2015-01-30 15:38:40 +0200 |
commit | 0aa20dd26d641dcaeb19efc1028e408910032e93 (patch) | |
tree | 21615c28df840397dcd399c3f055c166e19dd51d | |
parent | 6aad65375b265bced5758cd147b89fe26ca5edff (diff) | |
download | qt-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>
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); |