diff --git a/lib/platform.cpp b/lib/platform.cpp index 833c012ab8e..f74def9de61 100644 --- a/lib/platform.cpp +++ b/lib/platform.cpp @@ -51,11 +51,7 @@ bool Platform::set(Type t) sizeof_wchar_t = sizeof(wchar_t); sizeof_size_t = sizeof(std::size_t); sizeof_pointer = sizeof(void *); - if (type == Type::Unspecified) { - defaultSign = '\0'; - } else { - defaultSign = std::numeric_limits::is_signed ? 's' : 'u'; - } + defaultSign = std::numeric_limits::is_signed ? 's' : 'u'; char_bit = 8; calculateBitMembers(); return true; @@ -73,7 +69,7 @@ bool Platform::set(Type t) sizeof_wchar_t = 2; sizeof_size_t = 4; sizeof_pointer = 4; - defaultSign = '\0'; + defaultSign = 's'; char_bit = 8; calculateBitMembers(); return true; @@ -90,7 +86,7 @@ bool Platform::set(Type t) sizeof_wchar_t = 2; sizeof_size_t = 8; sizeof_pointer = 8; - defaultSign = '\0'; + defaultSign = 's'; char_bit = 8; calculateBitMembers(); return true; @@ -107,7 +103,7 @@ bool Platform::set(Type t) sizeof_wchar_t = 4; sizeof_size_t = 4; sizeof_pointer = 4; - defaultSign = '\0'; + defaultSign = 's'; char_bit = 8; calculateBitMembers(); return true; @@ -124,7 +120,7 @@ bool Platform::set(Type t) sizeof_wchar_t = 4; sizeof_size_t = 8; sizeof_pointer = 8; - defaultSign = '\0'; + defaultSign = 's'; char_bit = 8; calculateBitMembers(); return true; @@ -151,7 +147,10 @@ bool Platform::set(const std::string& platformstr, std::string& errstr, const st else if (platformstr == "native") set(Type::Native); else if (platformstr == "unspecified") + { + std::cout << "Platform 'unspecified' is deprecated and will be removed in a future version. It is also now identical to 'native' (i.e. char type signedness based on compiler instead of unknown)." << std::endl; set(Type::Unspecified); + } else if (paths.empty()) { errstr = "unrecognized platform: '" + platformstr + "' (no lookup)."; return false; @@ -228,7 +227,8 @@ bool Platform::loadFromFile(const std::vector& paths, const std::st if (err != tinyxml2::XML_SUCCESS) return false; - return loadFromXmlDocument(&doc); + std::string errmsg; // TODO + return loadFromXmlDocument(&doc, errmsg); } static unsigned int xmlTextAsUInt(const tinyxml2::XMLElement* node, bool& error) @@ -239,19 +239,30 @@ static unsigned int xmlTextAsUInt(const tinyxml2::XMLElement* node, bool& error) return retval; } -bool Platform::loadFromXmlDocument(const tinyxml2::XMLDocument *doc) +bool Platform::loadFromXmlDocument(const tinyxml2::XMLDocument *doc, std::string& errmsg) { const tinyxml2::XMLElement * const rootnode = doc->FirstChildElement(); - if (!rootnode || std::strcmp(rootnode->Name(), "platform") != 0) + if (!rootnode) + { + errmsg = "no root node found"; return false; + } - bool error = false; + if (std::strcmp(rootnode->Name(), "platform") != 0) + { + errmsg = "invalid root node"; + return false; + } + + // TODO: improve error reporting + bool res = true; for (const tinyxml2::XMLElement *node = rootnode->FirstChildElement(); node; node = node->NextSiblingElement()) { + bool error = false; const char* name = node->Name(); if (std::strcmp(name, "default-sign") == 0) { const char* str = node->GetText(); - if (str) + if (str && (*str == 'u' || *str == 's')) defaultSign = *str; else error = true; @@ -284,10 +295,15 @@ bool Platform::loadFromXmlDocument(const tinyxml2::XMLDocument *doc) sizeof_wchar_t = xmlTextAsUInt(sz, error); } } + if (error) + { + res = false; + errmsg = std::string("'") + name + "' failed"; + } } calculateBitMembers(); type = Type::File; - return !error; + return res; } std::string Platform::getLimitsDefines(bool c99) const diff --git a/lib/platform.h b/lib/platform.h index 4673c4859e6..596a36c3c51 100644 --- a/lib/platform.h +++ b/lib/platform.h @@ -81,7 +81,7 @@ class CPPCHECKLIB Platform { protected: /** load platform from xml document, primarily for testing */ - bool loadFromXmlDocument(const tinyxml2::XMLDocument *doc); + bool loadFromXmlDocument(const tinyxml2::XMLDocument *doc, std::string& errmsg); public: Platform(); @@ -130,7 +130,7 @@ class CPPCHECKLIB Platform { std::size_t sizeof_size_t; std::size_t sizeof_pointer; - char defaultSign; // unsigned:'u', signed:'s', unknown:'\0' + char defaultSign; // unsigned:'u', signed:'s' enum Type : std::uint8_t { Unspecified, // No platform specified diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b6528d9a9e6..c438c75f7a6 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -64,12 +64,10 @@ SymbolDatabase::SymbolDatabase(Tokenizer& tokenizer) if (!mTokenizer.tokens()) return; - if (mSettings.platform.defaultSign == 's' || mSettings.platform.defaultSign == 'S') - mDefaultSignedness = ValueType::SIGNED; - else if (mSettings.platform.defaultSign == 'u' || mSettings.platform.defaultSign == 'U') + if (mSettings.platform.defaultSign == 'u') mDefaultSignedness = ValueType::UNSIGNED; else - mDefaultSignedness = ValueType::UNKNOWN_SIGN; + mDefaultSignedness = ValueType::SIGNED; createSymbolDatabaseFindAllScopes(); createSymbolDatabaseClassInfo(); diff --git a/releasenotes.txt b/releasenotes.txt index 919e355fb1b..a30c42c43db 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -14,7 +14,13 @@ GUI: - Changed interface: +- The "unspecified" platform has been deprecated and will be removed in a future version. It is also now identical to 'native' (i.e. char type signedness based on compiler instead of unknown). - Infrastructure & dependencies: - + +Other: +- The possibility of an unknown signedness of the char type in a platform definition has been removed. +- The built-in "win*" and "unix*" platforms will now default to signed char type instead of unknown signedness. If you require unsigned chars please specify "--funsigned-char" +- diff --git a/test/cli/other_test.py b/test/cli/other_test.py index c4ae2fab5cf..73f3c5b643f 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -4119,3 +4119,88 @@ def test_active_unusedfunction_only_misra_builddir(tmp_path): 'CheckUnusedFunctions::check' ] __test_active_checkers(tmp_path, 1, 1175, use_unusedfunction_only=True, use_misra=True, checkers_exp=checkers_exp) + + +def test_platform_custom(tmp_path): + test_cfg = tmp_path / 'test.cfg' + with open(test_cfg, 'wt') as f: + f.write(""" + + + 8 + unsigned + + 1 + 2 + 2 + 4 + 8 + 4 + 4 + 4 + 2 + 2 + 2 + + + """) + + # TODO: use a sample to make sure the file is actually used + test_file = tmp_path / 'test.c' + with open(test_file, 'wt') as f: + f.write("""""") + + args = [ + '--platform={}'.format(test_cfg), + str(test_file) + ] + + exitcode, stdout, stderr = cppcheck(args) + assert exitcode == 0, stdout + lines = stdout.splitlines() + assert lines == [ + 'Checking {} ...'.format(test_file) + ] + assert stderr == '' + + +def test_platform_invalid_defaultsign(tmp_path): + test_cfg = tmp_path / 'test.cfg' + with open(test_cfg, 'wt') as f: + f.write(""" + + + 8 + notsigned + + 1 + 2 + 2 + 4 + 8 + 4 + 4 + 4 + 2 + 2 + 2 + + + """) + + test_file = tmp_path / 'test.c' + with open(test_file, 'wt') as f: + f.write("""""") + + args = [ + '--platform={}'.format(test_cfg), + str(test_file) + ] + + exitcode, stdout, stderr = cppcheck(args) + assert exitcode == 0, stdout + lines = stdout.splitlines() + assert lines == [ + 'Checking {} ...'.format(test_file) + ] + assert stderr == '' diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 7b5c646e4bf..8a596269749 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -1799,7 +1799,6 @@ class TestCmdlineParser : public TestFixture { void platformWin64() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=win64", "file.cpp"}; - ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(Platform::Type::Win64, settings->platform.type); } @@ -1807,7 +1806,6 @@ class TestCmdlineParser : public TestFixture { void platformWin32A() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=win32A", "file.cpp"}; - ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(Platform::Type::Win32A, settings->platform.type); } @@ -1815,7 +1813,6 @@ class TestCmdlineParser : public TestFixture { void platformWin32W() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=win32W", "file.cpp"}; - ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(Platform::Type::Win32W, settings->platform.type); } @@ -1823,7 +1820,6 @@ class TestCmdlineParser : public TestFixture { void platformUnix32() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=unix32", "file.cpp"}; - ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(Platform::Type::Unix32, settings->platform.type); } @@ -1831,7 +1827,6 @@ class TestCmdlineParser : public TestFixture { void platformUnix32Unsigned() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=unix32-unsigned", "file.cpp"}; - ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); ASSERT_EQUALS("cppcheck: error: unrecognized platform: 'unix32-unsigned'.\n", logger->str()); } @@ -1839,7 +1834,6 @@ class TestCmdlineParser : public TestFixture { void platformUnix64() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=unix64", "file.cpp"}; - ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(Platform::Type::Unix64, settings->platform.type); } @@ -1847,7 +1841,6 @@ class TestCmdlineParser : public TestFixture { void platformUnix64Unsigned() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=unix64-unsigned", "file.cpp"}; - ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv)); ASSERT_EQUALS("cppcheck: error: unrecognized platform: 'unix64-unsigned'.\n", logger->str()); } @@ -1855,7 +1848,6 @@ class TestCmdlineParser : public TestFixture { void platformNative() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=native", "file.cpp"}; - ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(Platform::Type::Native, settings->platform.type); } @@ -1863,7 +1855,6 @@ class TestCmdlineParser : public TestFixture { void platformUnspecified() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=unspecified", "file.cpp"}; - ASSERT(settings->platform.set(Platform::Type::Native)); ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(Platform::Type::Unspecified, settings->platform.type); } @@ -1871,7 +1862,6 @@ class TestCmdlineParser : public TestFixture { void platformPlatformFile() { REDIRECT; const char * const argv[] = {"cppcheck", "--platform=avr8", "file.cpp"}; - ASSERT(settings->platform.set(Platform::Type::Unspecified)); ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); ASSERT_EQUALS(Platform::Type::File, settings->platform.type); } diff --git a/test/testplatform.cpp b/test/testplatform.cpp index c0f7bb2c017..8d98581643b 100644 --- a/test/testplatform.cpp +++ b/test/testplatform.cpp @@ -55,9 +55,9 @@ class TestPlatform : public TestFixture { friend class TestPlatform; }; - static bool readPlatform(PlatformTest& platform, const char* xmldata) { + static bool readPlatform(PlatformTest& platform, const char* xmldata, std::string& errmsg) { tinyxml2::XMLDocument doc; - return (doc.Parse(xmldata) == tinyxml2::XML_SUCCESS) && platform.loadFromXmlDocument(&doc); + return (doc.Parse(xmldata) == tinyxml2::XML_SUCCESS) && platform.loadFromXmlDocument(&doc, errmsg); } void empty() const { @@ -65,7 +65,9 @@ class TestPlatform : public TestFixture { constexpr char xmldata[] = "\n"; PlatformTest platform; // TODO: this should fail - platform files need to be complete - TODO_ASSERT(!readPlatform(platform, xmldata)); + std::string errmsg; + TODO_ASSERT(!readPlatform(platform, xmldata, errmsg)); + ASSERT_EQUALS("", errmsg); } void valid_config_win32a() const { @@ -85,7 +87,7 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(2, platform.sizeof_wchar_t); ASSERT_EQUALS(4, platform.sizeof_size_t); ASSERT_EQUALS(4, platform.sizeof_pointer); - ASSERT_EQUALS('\0', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(8, platform.char_bit); ASSERT_EQUALS(16, platform.short_bit); ASSERT_EQUALS(32, platform.int_bit); @@ -110,7 +112,7 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(4, platform.sizeof_wchar_t); ASSERT_EQUALS(8, platform.sizeof_size_t); ASSERT_EQUALS(8, platform.sizeof_pointer); - ASSERT_EQUALS('\0', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(8, platform.char_bit); ASSERT_EQUALS(16, platform.short_bit); ASSERT_EQUALS(32, platform.int_bit); @@ -138,7 +140,7 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(2, platform.sizeof_wchar_t); ASSERT_EQUALS(4, platform.sizeof_size_t); ASSERT_EQUALS(4, platform.sizeof_pointer); - ASSERT_EQUALS('\0', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(8, platform.char_bit); ASSERT_EQUALS(16, platform.short_bit); ASSERT_EQUALS(32, platform.int_bit); @@ -166,7 +168,7 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(4, platform.sizeof_wchar_t); ASSERT_EQUALS(4, platform.sizeof_size_t); ASSERT_EQUALS(4, platform.sizeof_pointer); - ASSERT_EQUALS('\0', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(8, platform.char_bit); ASSERT_EQUALS(16, platform.short_bit); ASSERT_EQUALS(32, platform.int_bit); @@ -194,7 +196,7 @@ class TestPlatform : public TestFixture { ASSERT_EQUALS(2, platform.sizeof_wchar_t); ASSERT_EQUALS(8, platform.sizeof_size_t); ASSERT_EQUALS(8, platform.sizeof_pointer); - ASSERT_EQUALS('\0', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(8, platform.char_bit); ASSERT_EQUALS(16, platform.short_bit); ASSERT_EQUALS(32, platform.int_bit); @@ -227,7 +229,10 @@ class TestPlatform : public TestFixture { " \n" " "; PlatformTest platform; - ASSERT(readPlatform(platform, xmldata)); + std::string errmsg; + ASSERT(readPlatform(platform, xmldata, errmsg)); + ASSERT_EQUALS("", errmsg); + ASSERT_EQUALS("", errmsg); ASSERT_EQUALS(Platform::Type::File, platform.type); ASSERT(!platform.isWindows()); ASSERT_EQUALS(8, platform.char_bit); @@ -271,7 +276,9 @@ class TestPlatform : public TestFixture { " \n" " "; PlatformTest platform; - ASSERT(readPlatform(platform, xmldata)); + std::string errmsg; + ASSERT(readPlatform(platform, xmldata, errmsg)); + ASSERT_EQUALS("", errmsg); ASSERT_EQUALS(Platform::Type::File, platform.type); ASSERT(!platform.isWindows()); ASSERT_EQUALS(20, platform.char_bit); @@ -316,7 +323,9 @@ class TestPlatform : public TestFixture { " "; PlatformTest platform; // TODO: needs to fail - files need to be complete - TODO_ASSERT(!readPlatform(platform, xmldata)); + std::string errmsg; + TODO_ASSERT(!readPlatform(platform, xmldata, errmsg)); + ASSERT_EQUALS("", errmsg); } void valid_config_file_4() const { @@ -325,7 +334,7 @@ class TestPlatform : public TestFixture { constexpr char xmldata[] = "\n" "\n" " 0\n" - " z\n" + " s\n" " \n" " 0\n" " 0\n" @@ -341,11 +350,13 @@ class TestPlatform : public TestFixture { " \n" " "; PlatformTest platform; - ASSERT(readPlatform(platform, xmldata)); + std::string errmsg; + ASSERT(readPlatform(platform, xmldata, errmsg)); + ASSERT_EQUALS("", errmsg); ASSERT_EQUALS(Platform::Type::File, platform.type); ASSERT(!platform.isWindows()); ASSERT_EQUALS(0, platform.char_bit); - ASSERT_EQUALS('z', platform.defaultSign); + ASSERT_EQUALS('s', platform.defaultSign); ASSERT_EQUALS(0, platform.sizeof_bool); ASSERT_EQUALS(0, platform.sizeof_short); ASSERT_EQUALS(0, platform.sizeof_int); @@ -384,7 +395,9 @@ class TestPlatform : public TestFixture { " \n" " "; PlatformTest platform; - ASSERT(!readPlatform(platform, xmldata)); + std::string errmsg; + ASSERT(!readPlatform(platform, xmldata, errmsg)); + ASSERT_EQUALS("", errmsg); } void empty_elements() const { @@ -409,7 +422,9 @@ class TestPlatform : public TestFixture { " \n" " "; PlatformTest platform; - ASSERT(!readPlatform(platform, xmldata)); + std::string errmsg; + ASSERT(!readPlatform(platform, xmldata, errmsg)); + ASSERT_EQUALS("'sizeof' failed", errmsg); // TODO: improve message } void default_platform() const { @@ -440,15 +455,21 @@ class TestPlatform : public TestFixture { void no_root_node() const { constexpr char xmldata[] = ""; PlatformTest platform; - ASSERT(!readPlatform(platform, xmldata)); + std::string errmsg; + ASSERT(!readPlatform(platform, xmldata, errmsg)); + ASSERT_EQUALS("no root node found", errmsg); } void wrong_root_node() const { constexpr char xmldata[] = "\n" ""; PlatformTest platform; - ASSERT(!readPlatform(platform, xmldata)); + std::string errmsg; + ASSERT(!readPlatform(platform, xmldata, errmsg)); + ASSERT_EQUALS("invalid root node", errmsg); } + + // TODO: test unspecified }; REGISTER_TEST(TestPlatform)