greatly improved error handling in Cppcheck project file parsing / some cleanups (#4752)

This commit is contained in:
Oliver Stöneberg 2023-02-08 20:30:43 +01:00 committed by GitHub
parent 0dddba3bd6
commit 14e78e1800
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 300 additions and 110 deletions

View File

@ -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<std::string> 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<std::string> 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")

View File

@ -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<QAction *>(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);
}
}

View File

@ -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<Platform>::iterator iter = mPlatforms.begin();
while (iter != mPlatforms.end()) {

View File

@ -19,7 +19,7 @@
#ifndef PLATFORMS_H
#define PLATFORMS_H
#include "settings.h"
#include "platform.h"
#include <QList>
#include <QObject>
@ -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<Platform> mPlatforms;
};

View File

@ -53,7 +53,6 @@ void ProjectFile::clear()
mRootPath.clear();
mBuildDir.clear();
mImportProject.clear();
mAnalyzeAllVsConfigs = true;
mIncludeDirs.clear();
mDefines.clear();
mUndefines.clear();

View File

@ -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;

View File

@ -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());

View File

@ -1119,6 +1119,9 @@ static std::string istream_to_string(std::istream &istr)
return std::string(std::istreambuf_iterator<char>(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<std::string> filenames;
for (std::list<ImportProject::FileSettings>::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;

View File

@ -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";

View File

@ -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<std::string>& 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

View File

@ -25,6 +25,7 @@
#include <climits>
#include <string>
#include <vector>
/// @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<std::string>& paths = {}, bool verbose = false);
/**
* load platform file
* @param exename application path

View File

@ -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;

View File

@ -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.

View File

@ -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 = '<platform>{}</platform>'.format(platform)
if importproject is not None:
platform = '<importproject>{}</importproject>'.format(importproject)
with open(project_file, 'wt') as f:
f.write(
"""<?xml version="1.0" encoding="UTF-8"?>
<project version="1">
{}
{}
<paths>
<dir name="."/>
</paths>
</project>""".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("""
<?xml version="1.0" encoding="UTF-8"?>
<project version="1">
<platform>p1.xml</platform>
<paths>
<dir name="."/>
</paths>
</project>
""")
project_file = __write_cppcheck_project_file(tmpdir, platform='p1.xml')
with open(os.path.join(tmpdir, 'p1.xml'), 'wt') as f:
f.write('<?xml version="1.0"?>\n<platform/>')
@ -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(
"""<?xml version="1.0" encoding="UTF-8"?>
<project version="1">
<root/>
<builddir/>
<includedir/>
<includedir>
<dir/>
</includedir>
<defines/>
<defines>
<define/>
</defines>
<undefines/>
<undefines>
<undefine/>
</undefines>
<importproject/>
<paths/>
<paths>
<dir/>
</paths>
<exclude/>
<exclude>
<paths/>
</exclude>
<function-contracts/>
<variable-contracts/>
<ignore/>
<ignore>
<path/>
</ignore>
<libraries/>
<libraries>
<library/>
</libraries>
<suppressions/>
<suppressions>
<suppression/>
</suppressions>
<vs-configurations/>
<vs-configurations>
<config/>
</vs-configurations>
<platform/>
<analyze-all-vs-configs/>
<parser/>
<addons/>
<addons>
<addon/>
</addons>
<tags/>
<tools/>
<tools>
<tool/>
</tools>
<check-headers/>
<check-unused-templates/>
<max-ctu-depth/>
<max-template-recursion/>
<check-unknown-function-return-values/>
<safe-checks/>
<safe-checks>
<class-public/>
<external-functions/>
<internal-functions/>
<external-variables/>
</safe-checks>
<tag-warnings/>
<bug-hunting/>
<cert-c-int-precision/>
<coding-standards/>
<coding-standards>
<coding-standard/>
</coding-standards>
</project>""")
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 == ''

View File

@ -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

View File

@ -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)