diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 3543521d0..f0045ae71 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -603,25 +603,10 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) else if (std::strncmp(argv[i], "--platform=", 11) == 0) { const std::string platform(11+argv[i]); - if (platform == "win32A") - mSettings->platform(Settings::Win32A); - else if (platform == "win32W") - mSettings->platform(Settings::Win32W); - else if (platform == "win64") - mSettings->platform(Settings::Win64); - else if (platform == "unix32") - mSettings->platform(Settings::Unix32); - else if (platform == "unix64") - mSettings->platform(Settings::Unix64); - else if (platform == "native") - mSettings->platform(Settings::Native); - else if (platform == "unspecified") - mSettings->platform(Settings::Unspecified); - else if (!mSettings->loadPlatformFile(argv[0], platform, mSettings->verbose)) { - std::string message("unrecognized platform: \""); - message += platform; - message += "\"."; - printError(message); + std::string errstr; + const std::vector paths = {argv[0]}; + if (!mSettings->platform(platform, errstr, paths)) { + printError(errstr); return false; } @@ -669,7 +654,7 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) // --project else if (std::strncmp(argv[i], "--project=", 10) == 0) { mSettings->checkAllConfigurations = false; // Can be overridden with --max-configs or --force - const std::string projectFile = argv[i]+10; + std::string projectFile = argv[i]+10; ImportProject::Type projType = mSettings->project.import(projectFile, mSettings); mSettings->project.projectType = projType; if (projType == ImportProject::Type::CPPCHECK_GUI) { @@ -680,32 +665,27 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[]) const auto& excludedPaths = mSettings->project.guiProject.excludedPaths; std::copy(excludedPaths.cbegin(), excludedPaths.cend(), std::back_inserter(mIgnoredPaths)); - const std::string platform(mSettings->project.guiProject.platform); + std::string platform(mSettings->project.guiProject.platform); - if (platform == "win32A") - mSettings->platform(Settings::Win32A); - else if (platform == "win32W") - mSettings->platform(Settings::Win32W); - else if (platform == "win64") - mSettings->platform(Settings::Win64); - else if (platform == "unix32") - mSettings->platform(Settings::Unix32); - else if (platform == "unix64") - mSettings->platform(Settings::Unix64); - else if (platform == "native") - mSettings->platform(Settings::Native); - else if (platform == "unspecified" || platform == "Unspecified" || platform.empty()) - ; - else if (!mSettings->loadPlatformFile(projectFile.c_str(), platform, mSettings->verbose) && !mSettings->loadPlatformFile(argv[0], platform, mSettings->verbose)) { - std::string message("unrecognized platform: \""); - message += platform; - message += "\"."; - printError(message); - return false; + // keep existing platform from command-line intact + if (!platform.empty()) { + if (platform == "Unspecified") { + printMessage("'Unspecified' is a deprecated platform type and will be removed in Cppcheck 2.14. Please use 'unspecified' instead."); + platform = "unspecified"; + } + + std::string errstr; + const std::vector paths = {projectFile, argv[0]}; + if (!mSettings->platform(platform, errstr, paths)) { + printError(errstr); + return false; + } } - if (!mSettings->project.guiProject.projectFile.empty()) + if (!mSettings->project.guiProject.projectFile.empty()) { + projectFile = mSettings->project.guiProject.projectFile; projType = mSettings->project.import(mSettings->project.guiProject.projectFile, mSettings); + } } if (projType == ImportProject::Type::VS_SLN || projType == ImportProject::Type::VS_VCXPROJ) { if (mSettings->project.guiProject.analyzeAllVsConfigs == "false") diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 9188ffe62..eb35e79fb 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -257,11 +257,11 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) : // For other platforms default to unspecified/default which means the // platform Cppcheck GUI was compiled on. #if defined(_WIN32) - const Settings::PlatformType defaultPlatform = Settings::Win32W; + const cppcheck::Platform::PlatformType defaultPlatform = cppcheck::Platform::Win32W; #else - const Settings::PlatformType defaultPlatform = Settings::Unspecified; + const cppcheck::Platform::PlatformType defaultPlatform = cppcheck::Platform::Unspecified; #endif - Platform &platform = mPlatforms.get((Settings::PlatformType)mSettings->value(SETTINGS_CHECKED_PLATFORM, defaultPlatform).toInt()); + Platform &platform = mPlatforms.get((cppcheck::Platform::PlatformType)mSettings->value(SETTINGS_CHECKED_PLATFORM, defaultPlatform).toInt()); platform.mActMainWindow->setChecked(true); mNetworkAccessManager = new QNetworkAccessManager(this); @@ -477,7 +477,7 @@ void MainWindow::doAnalyzeProject(ImportProject p, const bool checkLibrary, cons p.ignorePaths(v); if (!mProjectFile->getAnalyzeAllVsConfigs()) { - const Settings::PlatformType platform = (Settings::PlatformType) mSettings->value(SETTINGS_CHECKED_PLATFORM, 0).toInt(); + const cppcheck::Platform::PlatformType platform = (cppcheck::Platform::PlatformType) mSettings->value(SETTINGS_CHECKED_PLATFORM, 0).toInt(); p.selectOneVsConfig(platform); } } else { @@ -1908,7 +1908,7 @@ void MainWindow::selectPlatform() { QAction *action = qobject_cast(sender()); if (action) { - const Settings::PlatformType platform = (Settings::PlatformType) action->data().toInt(); + const cppcheck::Platform::PlatformType platform = (cppcheck::Platform::PlatformType) action->data().toInt(); mSettings->setValue(SETTINGS_CHECKED_PLATFORM, platform); } } diff --git a/gui/platforms.cpp b/gui/platforms.cpp index 2466abdd0..180025227 100644 --- a/gui/platforms.cpp +++ b/gui/platforms.cpp @@ -24,7 +24,7 @@ Platforms::Platforms(QObject *parent) init(); } -void Platforms::add(const QString &title, Settings::PlatformType platform) +void Platforms::add(const QString &title, cppcheck::Platform::PlatformType platform) { Platform plat; plat.mTitle = title; @@ -35,12 +35,12 @@ void Platforms::add(const QString &title, Settings::PlatformType platform) void Platforms::init() { - add(tr("Native"), Settings::Native); - add(tr("Unix 32-bit"), Settings::Unix32); - add(tr("Unix 64-bit"), Settings::Unix64); - add(tr("Windows 32-bit ANSI"), Settings::Win32A); - add(tr("Windows 32-bit Unicode"), Settings::Win32W); - add(tr("Windows 64-bit"), Settings::Win64); + add(tr("Native"), cppcheck::Platform::Native); + add(tr("Unix 32-bit"), cppcheck::Platform::Unix32); + add(tr("Unix 64-bit"), cppcheck::Platform::Unix64); + add(tr("Windows 32-bit ANSI"), cppcheck::Platform::Win32A); + add(tr("Windows 32-bit Unicode"), cppcheck::Platform::Win32W); + add(tr("Windows 64-bit"), cppcheck::Platform::Win64); } int Platforms::getCount() const @@ -48,7 +48,7 @@ int Platforms::getCount() const return mPlatforms.count(); } -Platform& Platforms::get(Settings::PlatformType platform) +Platform& Platforms::get(cppcheck::Platform::PlatformType platform) { QList::iterator iter = mPlatforms.begin(); while (iter != mPlatforms.end()) { diff --git a/gui/platforms.h b/gui/platforms.h index f4f6ef6e3..7b7fd4f4c 100644 --- a/gui/platforms.h +++ b/gui/platforms.h @@ -19,7 +19,7 @@ #ifndef PLATFORMS_H #define PLATFORMS_H -#include "settings.h" +#include "platform.h" #include #include @@ -35,7 +35,7 @@ class QAction; */ struct Platform { QString mTitle; /**< Text visible in the GUI. */ - Settings::PlatformType mType; /**< Type in the core. */ + cppcheck::Platform::PlatformType mType; /**< Type in the core. */ QAction *mActMainWindow; /**< Pointer to main window action item. */ }; @@ -47,10 +47,10 @@ class Platforms : public QObject { public: explicit Platforms(QObject *parent = nullptr); - void add(const QString &title, Settings::PlatformType platform); + void add(const QString &title, cppcheck::Platform::PlatformType platform); int getCount() const; void init(); - Platform& get(Settings::PlatformType platform); + Platform& get(cppcheck::Platform::PlatformType platform); QList mPlatforms; }; diff --git a/gui/projectfile.cpp b/gui/projectfile.cpp index 03e02338a..2d4537f92 100644 --- a/gui/projectfile.cpp +++ b/gui/projectfile.cpp @@ -53,7 +53,6 @@ void ProjectFile::clear() mRootPath.clear(); mBuildDir.clear(); mImportProject.clear(); - mAnalyzeAllVsConfigs = true; mIncludeDirs.clear(); mDefines.clear(); mUndefines.clear(); diff --git a/lib/checktype.cpp b/lib/checktype.cpp index 891055efd..0b6ba6c3c 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -57,7 +57,7 @@ static const struct CWE CWE190(190U); // Integer Overflow or Wraparound void CheckType::checkTooBigBitwiseShift() { // unknown sizeof(int) => can't run this checker - if (mSettings->platformType == Settings::Unspecified) + if (mSettings->platformType == cppcheck::Platform::Unspecified) return; for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { @@ -160,7 +160,7 @@ void CheckType::tooBigSignedBitwiseShiftError(const Token *tok, int lhsbits, con void CheckType::checkIntegerOverflow() { // unknown sizeof(int) => can't run this checker - if (mSettings->platformType == Settings::Unspecified || mSettings->int_bit >= MathLib::bigint_bits) + if (mSettings->platformType == cppcheck::Platform::Unspecified || mSettings->int_bit >= MathLib::bigint_bits) return; for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { @@ -436,7 +436,7 @@ void CheckType::checkFloatToIntegerOverflow(const Token *tok, const ValueType *v floatToIntegerOverflowError(tok, f); else if ((-f.floatValue) > std::exp2(mSettings->long_long_bit - 1)) floatToIntegerOverflowError(tok, f); - else if (mSettings->platformType != Settings::Unspecified) { + else if (mSettings->platformType != cppcheck::Platform::Unspecified) { int bits = 0; if (vtint->type == ValueType::Type::CHAR) bits = mSettings->char_bit; diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index da577d71d..a3f387b2e 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -586,7 +586,7 @@ unsigned int CppCheck::check(const ImportProject::FileSettings &fs) temp.mSettings.standards.setCPP(fs.standard); else if (!fs.standard.empty()) temp.mSettings.standards.setC(fs.standard); - if (fs.platformType != Settings::Unspecified) + if (fs.platformType != cppcheck::Platform::Unspecified) temp.mSettings.platform(fs.platformType); if (mSettings.clang) { temp.mSettings.includePaths.insert(temp.mSettings.includePaths.end(), fs.systemIncludePaths.cbegin(), fs.systemIncludePaths.cend()); diff --git a/lib/importproject.cpp b/lib/importproject.cpp index d622fec5a..164c861ea 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -1119,6 +1119,9 @@ static std::string istream_to_string(std::istream &istr) return std::string(std::istreambuf_iterator(istr), eos); } +static const char * readSafe(const char *s, const char *def) { + return s ? s : def; +} bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *settings) { @@ -1144,13 +1147,13 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti guiProject.analyzeAllVsConfigs.clear(); for (const tinyxml2::XMLElement *node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) { - if (strcmp(node->Name(), CppcheckXml::RootPathName) == 0 && node->Attribute(CppcheckXml::RootPathNameAttrib)) { - temp.basePaths.push_back(joinRelativePath(path, node->Attribute(CppcheckXml::RootPathNameAttrib))); - temp.relativePaths = true; - } else if (strcmp(node->Name(), CppcheckXml::BugHunting) == 0) - ; - else if (strcmp(node->Name(), CppcheckXml::BuildDirElementName) == 0) - temp.buildDir = joinRelativePath(path, node->GetText() ? node->GetText() : ""); + if (strcmp(node->Name(), CppcheckXml::RootPathName) == 0) { + if (node->Attribute(CppcheckXml::RootPathNameAttrib)) { + temp.basePaths.push_back(joinRelativePath(path, node->Attribute(CppcheckXml::RootPathNameAttrib))); + temp.relativePaths = true; + } + } else if (strcmp(node->Name(), CppcheckXml::BuildDirElementName) == 0) + temp.buildDir = joinRelativePath(path, readSafe(node->GetText(), "")); else if (strcmp(node->Name(), CppcheckXml::IncludeDirElementName) == 0) temp.includePaths = readXmlStringList(node, path, CppcheckXml::DirElementName, CppcheckXml::DirNameAttrib); else if (strcmp(node->Name(), CppcheckXml::DefinesElementName) == 0) @@ -1158,8 +1161,11 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti else if (strcmp(node->Name(), CppcheckXml::UndefinesElementName) == 0) { for (const std::string &u : readXmlStringList(node, "", CppcheckXml::UndefineName, nullptr)) temp.userUndefs.insert(u); - } else if (strcmp(node->Name(), CppcheckXml::ImportProjectElementName) == 0) - guiProject.projectFile = path + (node->GetText() ? node->GetText() : ""); + } else if (strcmp(node->Name(), CppcheckXml::ImportProjectElementName) == 0) { + const std::string t_str = readSafe(node->GetText(), ""); + if (!t_str.empty()) + guiProject.projectFile = path + t_str; + } else if (strcmp(node->Name(), CppcheckXml::PathsElementName) == 0) paths = readXmlStringList(node, path, CppcheckXml::PathName, CppcheckXml::PathNameAttrib); else if (strcmp(node->Name(), CppcheckXml::ExcludeElementName) == 0) @@ -1176,25 +1182,22 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti for (const tinyxml2::XMLElement *child = node->FirstChildElement(); child; child = child->NextSiblingElement()) { if (strcmp(child->Name(), CppcheckXml::SuppressionElementName) != 0) continue; - auto read = [](const char *s, const char *def) { - return s ? s : def; - }; Suppressions::Suppression s; - s.errorId = read(child->GetText(), ""); - s.fileName = read(child->Attribute("fileName"), ""); + s.errorId = readSafe(child->GetText(), ""); + s.fileName = readSafe(child->Attribute("fileName"), ""); if (!s.fileName.empty()) s.fileName = joinRelativePath(path, s.fileName); s.lineNumber = child->IntAttribute("lineNumber", Suppressions::Suppression::NO_LINE); - s.symbolName = read(child->Attribute("symbolName"), ""); - std::istringstream(read(child->Attribute("hash"), "0")) >> s.hash; + s.symbolName = readSafe(child->Attribute("symbolName"), ""); + std::istringstream(readSafe(child->Attribute("hash"), "0")) >> s.hash; suppressions.push_back(std::move(s)); } } else if (strcmp(node->Name(), CppcheckXml::VSConfigurationElementName) == 0) guiProject.checkVsConfigs = readXmlStringList(node, emptyString, CppcheckXml::VSConfigurationName, nullptr); else if (strcmp(node->Name(), CppcheckXml::PlatformElementName) == 0) - guiProject.platform = node->GetText(); + guiProject.platform = readSafe(node->GetText(), ""); else if (strcmp(node->Name(), CppcheckXml::AnalyzeAllVsConfigsElementName) == 0) - guiProject.analyzeAllVsConfigs = node->GetText(); + guiProject.analyzeAllVsConfigs = readSafe(node->GetText(), ""); else if (strcmp(node->Name(), CppcheckXml::Parser) == 0) temp.clang = true; else if (strcmp(node->Name(), CppcheckXml::AddonsElementName) == 0) { @@ -1210,13 +1213,13 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti temp.clangTidy = true; } } else if (strcmp(node->Name(), CppcheckXml::CheckHeadersElementName) == 0) - temp.checkHeaders = (strcmp(node->GetText(), "true") == 0); + temp.checkHeaders = (strcmp(readSafe(node->GetText(), ""), "true") == 0); else if (strcmp(node->Name(), CppcheckXml::CheckUnusedTemplatesElementName) == 0) - temp.checkUnusedTemplates = (strcmp(node->GetText(), "true") == 0); + temp.checkUnusedTemplates = (strcmp(readSafe(node->GetText(), ""), "true") == 0); else if (strcmp(node->Name(), CppcheckXml::MaxCtuDepthElementName) == 0) - temp.maxCtuDepth = std::atoi(node->GetText()); + temp.maxCtuDepth = std::atoi(readSafe(node->GetText(), "")); // TODO: get rid of atoi() else if (strcmp(node->Name(), CppcheckXml::MaxTemplateRecursionElementName) == 0) - temp.maxTemplateRecursion = std::atoi(node->GetText()); + temp.maxTemplateRecursion = std::atoi(readSafe(node->GetText(), "")); // TODO: get rid of atoi() else if (strcmp(node->Name(), CppcheckXml::CheckUnknownFunctionReturn) == 0) ; // TODO else if (strcmp(node->Name(), Settings::SafeChecks::XmlRootName) == 0) { @@ -1229,8 +1232,10 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti temp.safeChecks.internalFunctions = true; else if (strcmp(child->Name(), Settings::SafeChecks::XmlExternalVariables) == 0) temp.safeChecks.externalVariables = true; - else + else { + printError("Unknown '" + std::string(Settings::SafeChecks::XmlRootName) + "' element '" + std::string(child->Name()) + "' in Cppcheck project file"); return false; + } } } else if (strcmp(node->Name(), CppcheckXml::TagWarningsElementName) == 0) ; // TODO @@ -1238,15 +1243,17 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti else if (strcmp(node->Name(), CppcheckXml::BughuntingElementName) == 0) temp.premiumArgs += " --bughunting"; else if (strcmp(node->Name(), CppcheckXml::CertIntPrecisionElementName) == 0) - temp.premiumArgs += std::string(" --cert-c-int-precision=") + (node->GetText() ? node->GetText() : "0"); + temp.premiumArgs += std::string(" --cert-c-int-precision=") + readSafe(node->GetText(), "0"); else if (strcmp(node->Name(), CppcheckXml::CodingStandardsElementName) == 0) { for (const tinyxml2::XMLElement *child = node->FirstChildElement(); child; child = child->NextSiblingElement()) { if (strcmp(child->Name(), CppcheckXml::CodingStandardElementName) == 0 && child->GetText()) temp.premiumArgs += std::string(" --") + child->GetText(); } } - else + else { + printError("Unknown element '" + std::string(node->Name()) + "' in Cppcheck project file"); return false; + } } settings->basePaths = temp.basePaths; settings->relativePaths |= temp.relativePaths; @@ -1276,7 +1283,7 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti return true; } -void ImportProject::selectOneVsConfig(Settings::PlatformType platform) +void ImportProject::selectOneVsConfig(cppcheck::Platform::PlatformType platform) { std::set filenames; for (std::list::iterator it = fileSettings.begin(); it != fileSettings.end();) { @@ -1288,11 +1295,11 @@ void ImportProject::selectOneVsConfig(Settings::PlatformType platform) bool remove = false; if (fs.cfg.compare(0,5,"Debug") != 0) remove = true; - if (platform == Settings::Win64 && fs.platformType != platform) + if (platform == cppcheck::Platform::Win64 && fs.platformType != platform) remove = true; - else if ((platform == Settings::Win32A || platform == Settings::Win32W) && fs.platformType == Settings::Win64) + else if ((platform == cppcheck::Platform::Win32A || platform == cppcheck::Platform::Win32W) && fs.platformType == cppcheck::Platform::Win64) remove = true; - else if (fs.platformType != Settings::Win64 && platform == Settings::Win64) + else if (fs.platformType != cppcheck::Platform::Win64 && platform == cppcheck::Platform::Win64) remove = true; else if (filenames.find(fs.filename) != filenames.end()) remove = true; diff --git a/lib/importproject.h b/lib/importproject.h index 213d8c0aa..ca931a7cf 100644 --- a/lib/importproject.h +++ b/lib/importproject.h @@ -133,7 +133,6 @@ namespace CppcheckXml { const char ImportProjectElementName[] = "importproject"; const char AnalyzeAllVsConfigsElementName[] = "analyze-all-vs-configs"; const char Parser[] = "parser"; - const char BugHunting[] = "bug-hunting"; const char IncludeDirElementName[] = "includedir"; const char DirElementName[] = "dir"; const char DirNameAttrib[] = "name"; diff --git a/lib/platform.cpp b/lib/platform.cpp index ade5f4541..4794a3758 100644 --- a/lib/platform.cpp +++ b/lib/platform.cpp @@ -157,6 +157,45 @@ bool cppcheck::Platform::platform(cppcheck::Platform::PlatformType type) return false; } +bool cppcheck::Platform::platform(const std::string& platformstr, std::string& errstr, const std::vector& paths, bool verbose) +{ + if (platformstr == "win32A") + platform(Win32A); + else if (platformstr == "win32W") + platform(Win32W); + else if (platformstr == "win64") + platform(Win64); + else if (platformstr == "unix32") + platform(Unix32); + else if (platformstr == "unix64") + platform(Unix64); + else if (platformstr == "native") + platform(Native); + else if (platformstr == "unspecified") + platform(Unspecified); + else if (paths.empty()) { + errstr = "unrecognized platform: '" + platformstr + "' (no lookup)."; + return false; + } + else { + bool found = false; + for (const std::string& path : paths) { + if (verbose) + std::cout << "looking for platform '" + platformstr + "' in '" + path + "'" << std::endl; + if (loadPlatformFile(path.c_str(), platformstr, verbose)) { + found = true; + break; + } + } + if (!found) { + errstr = "unrecognized platform: '" + platformstr + "'."; + return false; + } + } + + return true; +} + bool cppcheck::Platform::loadPlatformFile(const char exename[], const std::string &filename, bool verbose) { // TODO: only append .xml if missing diff --git a/lib/platform.h b/lib/platform.h index 74f4b9075..76fc87b55 100644 --- a/lib/platform.h +++ b/lib/platform.h @@ -25,6 +25,7 @@ #include #include +#include /// @addtogroup Core /// @{ @@ -113,9 +114,12 @@ namespace cppcheck { /** platform type */ PlatformType platformType; - /** set the platform type for predefined platforms */ + /** set the platform type for predefined platforms - deprecated use platform(const std::string&) instead */ bool platform(PlatformType type); + /** set the platform type */ + bool platform(const std::string& platformstr, std::string& errstr, const std::vector& paths = {}, bool verbose = false); + /** * load platform file * @param exename application path diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 4892745c1..1de644ccb 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9049,7 +9049,7 @@ void Tokenizer::simplifyMicrosoftStringFunctions() if (!mSettings->isWindowsPlatform()) return; - const bool ansi = mSettings->platformType == Settings::Win32A; + const bool ansi = mSettings->platformType == cppcheck::Platform::Win32A; for (Token *tok = list.front(); tok; tok = tok->next()) { if (tok->strAt(1) != "(") continue; diff --git a/releasenotes.txt b/releasenotes.txt index 3e413823b..9f18da67d 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -1,2 +1,3 @@ release notes for cppcheck-2.11 +- The platform type 'Unspecified' within .cppcheck projects has been deprecated and will be removed in Cppcheck 2.14. Please use 'unspecified' instead. \ No newline at end of file diff --git a/test/cli/test-more-projects.py b/test/cli/test-more-projects.py index fecdc4b71..6269d64a5 100644 --- a/test/cli/test-more-projects.py +++ b/test/cli/test-more-projects.py @@ -39,22 +39,34 @@ def test_project_force_U(tmpdir): assert stderr == '[bug1.cpp:2]: (error) Division by zero.\n' +def __write_cppcheck_project_file(tmpdir, platform=None, importproject=None): + project_file = os.path.join(tmpdir, 'Project.cppcheck') + + if platform is not None: + platform = '{}'.format(platform) + if importproject is not None: + platform = '{}'.format(importproject) + + with open(project_file, 'wt') as f: + f.write( +""" + + {} + {} + + + +""".format(platform, importproject) + ) + + return project_file + + def test_project_custom_platform(tmpdir): """ import cppcheck project that contains a custom platform file """ - project_file = os.path.join(tmpdir, 'Project.cppcheck') - - with open(project_file, 'wt') as f: - f.write(""" - - - p1.xml - - - - - """) + project_file = __write_cppcheck_project_file(tmpdir, platform='p1.xml') with open(os.path.join(tmpdir, 'p1.xml'), 'wt') as f: f.write('\n') @@ -62,6 +74,154 @@ def test_project_custom_platform(tmpdir): with open(os.path.join(tmpdir, '1.c'), 'wt') as f: f.write("int x;") - ret, stdout, stderr = cppcheck(['--project=' + project_file, '--template=cppcheck1']) + ret, stdout, stderr = cppcheck(['--platform=native', '--project=' + project_file, '--template=cppcheck1', '-q']) assert ret == 0, stdout + assert stdout == '' assert stderr == '' + + +def test_project_empty_platform(tmpdir): + """ + import cppcheck project that contains an empty platform type + """ + project_file = __write_cppcheck_project_file(tmpdir, platform='') + + with open(os.path.join(tmpdir, '1.c'), 'wt') as f: + f.write("int x;") + + ret, stdout, stderr = cppcheck(['--platform=native', '--project=' + project_file, '--template=cppcheck1', '-q']) + assert ret == 0, stdout + assert stdout == '' + assert stderr == '' + + +def test_project_unspecified_platform(tmpdir): + """ + import cppcheck project that contains the deprecated platform type "Unspecified" + """ + project_file = __write_cppcheck_project_file(tmpdir, platform='Unspecified') + + with open(os.path.join(tmpdir, '1.c'), 'wt') as f: + f.write("int x;") + + ret, stdout, stderr = cppcheck(['--platform=native', '--project=' + project_file, '--template=cppcheck1', '-q']) + assert ret == 0, stdout + assert stdout == "cppcheck: 'Unspecified' is a deprecated platform type and will be removed in Cppcheck 2.14. Please use 'unspecified' instead.\n" + assert stderr == '' + + +def test_project_unknown_platform(tmpdir): + """ + import cppcheck project that contains an unknown platform type + """ + project_file = __write_cppcheck_project_file(tmpdir, platform='dummy') + + with open(os.path.join(tmpdir, '1.c'), 'wt') as f: + f.write("int x;") + + ret, stdout, stderr = cppcheck(['--project=' + project_file, '--template=cppcheck1']) + assert ret == 1, stdout + assert stdout == "cppcheck: error: unrecognized platform: 'dummy'.\n" + assert stderr == '' + + +def test_project_empty_fields(tmpdir): + """ + import cppcheck project that contains all empty fields - make sure there are no crashes + """ + project_file = os.path.join(tmpdir, 'Project.cppcheck') + + with open(project_file, 'wt') as f: + f.write( +""" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +""") + + ret, stdout, stderr = cppcheck(['--platform=native', '--project=' + project_file, '--template=cppcheck1']) + assert ret == 1, stdout # do not crash + assert stdout == 'cppcheck: error: no C or C++ source files found.\n' + assert stderr == '' + + +def test_project_missing_subproject(tmpdir): + """ + import cppcheck project that contains an unknown platform type + """ + project_file = __write_cppcheck_project_file(tmpdir, importproject='dummy.json') + + ret, stdout, stderr = cppcheck(['--project=' + project_file, '--template=cppcheck1']) + assert ret == 1, stdout + assert stdout == "cppcheck: error: failed to open project '{}/dummy.json'. The file does not exist.\n".format(str(tmpdir).replace('\\', '/')) + assert stderr == '' \ No newline at end of file diff --git a/test/cli/testutils.py b/test/cli/testutils.py index 468b05c28..5b94b15a4 100644 --- a/test/cli/testutils.py +++ b/test/cli/testutils.py @@ -56,6 +56,7 @@ def lookup_cppcheck_exe(): for path in ('', 'bin/', 'bin/debug/'): exe_path = base + path + exe_name if os.path.isfile(exe_path): + print("using '{}'".format(exe_path)) return exe_path return None diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index becc25153..5d8a3c290 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -1076,7 +1076,7 @@ private: REDIRECT; const char * const argv[] = {"cppcheck", "--platform=win128", "file.cpp"}; ASSERT(!defParser.parseFromArgs(3, argv)); - ASSERT_EQUALS("cppcheck: error: unrecognized platform: \"win128\".\n", GET_REDIRECT_OUTPUT); + ASSERT_EQUALS("cppcheck: error: unrecognized platform: 'win128'.\n", GET_REDIRECT_OUTPUT); } #if defined(_WIN64) || defined(_WIN32)