diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 87022f58d..7f11ef0ad 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -695,6 +695,8 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) _settings->platform(Settings::Unix32); else if (platform == "unix64") _settings->platform(Settings::Unix64); + else if (platform == "avr8") + _settings->platform(Settings::AVR8); else if (platform == "native") _settings->platform(Settings::Native); else if (platform == "unspecified") @@ -941,6 +943,8 @@ void CmdLineParser::PrintHelp() " 32 bit Windows UNICODE character encoding\n" " * win64\n" " 64 bit Windows\n" + " * avr8\n" + " 8 bit AVR microcontrollers\n" " * native\n" " Type sizes of host system are assumed, but no\n" " further assumptions.\n" diff --git a/lib/platform.cpp b/lib/platform.cpp index 33422aed9..395e6c9d0 100644 --- a/lib/platform.cpp +++ b/lib/platform.cpp @@ -143,6 +143,26 @@ bool cppcheck::Platform::platform(cppcheck::Platform::PlatformType type) long_bit = char_bit * sizeof_long; long_long_bit = char_bit * sizeof_long_long; return true; + case AVR8: + platformType = type; + sizeof_bool = 1; + sizeof_short = 2; + sizeof_int = 2; + sizeof_long = 4; + sizeof_long_long = 8; + sizeof_float = 4; + sizeof_double = 4; + sizeof_long_double = 4; + sizeof_wchar_t = 2; + sizeof_size_t = 2; + sizeof_pointer = 2; + defaultSign = '\0'; + char_bit = 8; + short_bit = char_bit * sizeof_short; + int_bit = char_bit * sizeof_int; + long_bit = char_bit * sizeof_long; + long_long_bit = char_bit * sizeof_long_long; + return true; } // unsupported platform diff --git a/lib/platform.h b/lib/platform.h index a1165567a..347651319 100644 --- a/lib/platform.h +++ b/lib/platform.h @@ -85,7 +85,8 @@ namespace cppcheck { Win32W, Win64, Unix32, - Unix64 + Unix64, + AVR8 }; /** platform type */ @@ -119,6 +120,8 @@ namespace cppcheck { return "win32W"; case Win64: return "win64"; + case AVR8: + return "avr8"; default: return "unknown"; } diff --git a/test/testtype.cpp b/test/testtype.cpp index 70b50a002..000d55d39 100644 --- a/test/testtype.cpp +++ b/test/testtype.cpp @@ -34,7 +34,8 @@ private: void run() { - TEST_CASE(checkTooBigShift); + TEST_CASE(checkTooBigShift_Unix32); + TEST_CASE(checkTooBigShift_AVR8); TEST_CASE(checkIntegerOverflow); TEST_CASE(signConversion); TEST_CASE(longCastAssign); @@ -62,7 +63,59 @@ private: checkType.runChecks(&tokenizer, settings, this); } - void checkTooBigShift() { + void checkTooBigShift_AVR8() { + Settings settings; + settings.platform(Settings::AVR8); + + // int, short and size_t on AVR is 2 bytes long + { + check("int foo(int x) { return x << 17;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 16-bit value by 17 bits is undefined behaviour\n", errout.str()); + check("int foo(int x) { return x << 16;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 16-bit value by 16 bits is undefined behaviour\n", errout.str()); + check("int foo(int x) { return x << 15;}",&settings); + ASSERT_EQUALS("", errout.str()); + check("short foo(int x) { return x << 17;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 16-bit value by 17 bits is undefined behaviour\n", errout.str()); + check("short foo(int x) { return x << 16;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 16-bit value by 16 bits is undefined behaviour\n", errout.str()); + check("short foo(int x) { return x << 15;}",&settings); + ASSERT_EQUALS("", errout.str()); + check("size_t foo(int x) { return x << 17;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 16-bit value by 17 bits is undefined behaviour\n", errout.str()); + check("size_t foo(int x) { return x << 16;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 16-bit value by 16 bits is undefined behaviour\n", errout.str()); + check("size_t foo(int x) { return x << 15;}",&settings); + ASSERT_EQUALS("", errout.str()); + } + // long has four 4 bytes long + { + // downcast to int + check("long foo(long x) { return (int)x << 33;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 16-bit value by 33 bits is undefined behaviour\n", errout.str()); + check("long foo(long x) { return x << 33;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 32-bit value by 33 bits is undefined behaviour\n", errout.str()); + check("long foo(long x) { return x << 32;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 32-bit value by 32 bits is undefined behaviour\n", errout.str()); + check("long foo(long x) { return x << 31;}",&settings); + } + // long long is 8 bytes long + { + // downcast to int + check("long long foo(long long x) { return (int)x << 65;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 16-bit value by 65 bits is undefined behaviour\n", errout.str()); + // downcast to long + check("long long foo(long long x) { return (long)x << 65;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 32-bit value by 65 bits is undefined behaviour\n", errout.str()); + check("long long foo(long long x) { return x << 65;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 64-bit value by 65 bits is undefined behaviour\n", errout.str()); + check("long long foo(long long x) { return x << 64;}",&settings); + ASSERT_EQUALS("[test.cpp:1]: (error) Shifting 64-bit value by 64 bits is undefined behaviour\n", errout.str()); + check("long long foo(long long x) { return x << 63;}",&settings); + } + } + + void checkTooBigShift_Unix32() { Settings settings; settings.platform(Settings::Unix32);