CheckIO: Improved handling of h, hh, l, and ll.

This commit is contained in:
Robert Reif 2013-07-22 08:28:29 +02:00 committed by Daniel Marjamäki
parent 464dccc188
commit 20f81f92d9
2 changed files with 47 additions and 12 deletions

View File

@ -620,20 +620,34 @@ void CheckIO::checkWrongPrintfScanfArguments()
case 'l': // Can be 'll' (long long int or unsigned long long int) or 'l' (long int or unsigned long int) case 'l': // Can be 'll' (long long int or unsigned long long int) or 'l' (long int or unsigned long int)
// If the next character is the same (which makes 'hh' or 'll') then expect another alphabetical character // If the next character is the same (which makes 'hh' or 'll') then expect another alphabetical character
if (i != formatString.end() && *(i+1) == *i) { if (i != formatString.end() && *(i+1) == *i) {
if (i+1 != formatString.end() && !isalpha(*(i+2))) { if (i+1 != formatString.end()) {
std::string modifier; if (!isalpha(*(i+2))) {
modifier += *i; std::string modifier;
modifier += *(i+1); modifier += *i;
invalidLengthModifierError(tok, numFormat, modifier); modifier += *(i+1);
invalidLengthModifierError(tok, numFormat, modifier);
done = true;
} else {
specifier = *i++;
specifier += *i++;
}
} else {
done = true;
} }
} else { } else {
if (i != formatString.end() && !isalpha(*(i+1))) { if (i != formatString.end()) {
std::string modifier; if (!isalpha(*(i+1))) {
modifier += *i; std::string modifier;
invalidLengthModifierError(tok, numFormat, modifier); modifier += *i;
invalidLengthModifierError(tok, numFormat, modifier);
done = true;
} else {
specifier = *i++;
}
} else {
done = true;
} }
} }
done = true;
break; break;
case 'I': // Microsoft extension: I for size_t and ptrdiff_t, I32 for __int32, and I64 for __int64 case 'I': // Microsoft extension: I for size_t and ptrdiff_t, I32 for __int32, and I64 for __int64
if (i != formatString.end()) { if (i != formatString.end()) {
@ -659,8 +673,10 @@ void CheckIO::checkWrongPrintfScanfArguments()
std::string modifier; std::string modifier;
modifier += *i; modifier += *i;
invalidLengthModifierError(tok, numFormat, modifier); invalidLengthModifierError(tok, numFormat, modifier);
done = true;
} else {
specifier = *i++;
} }
done = true;
break; break;
default: default:
done = true; done = true;

View File

@ -717,7 +717,7 @@ private:
// False positive tests // False positive tests
check("void foo(signed char sc, unsigned char uc, short int si, unsigned short int usi) {\n" check("void foo(signed char sc, unsigned char uc, short int si, unsigned short int usi) {\n"
" printf(\"%hhx %hhd\", sc, uc);\n" " printf(\"%hhx %hhd\", sc, uc);\n"
" printf(\"%hd %hi\", si, usi);\n" " printf(\"%hd %hu\", si, usi);\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
@ -754,6 +754,25 @@ private:
"[test.cpp:7]: (warning) 'z' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n" "[test.cpp:7]: (warning) 'z' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
"[test.cpp:8]: (warning) 't' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n" "[test.cpp:8]: (warning) 't' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
"[test.cpp:9]: (warning) 'L' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n", errout.str()); "[test.cpp:9]: (warning) 'L' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n", errout.str());
check("void foo(unsigned int i) {\n"
" printf(\"%hd\", i);\n"
" printf(\"%hhd\", i);\n"
" printf(\"%ld\", i);\n"
" printf(\"%lld\", i);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) %hd in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:3]: (warning) %hhd in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:4]: (warning) %ld in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:5]: (warning) %lld in format string (no. 1) requires a signed integer given in the argument list.\n" , errout.str());
check("void foo(size_t s, ptrdiff_t p) {\n"
" printf(\"%zd\", s);\n"
" printf(\"%tu\", p);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning) %zd in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:3]: (warning) %tu in format string (no. 1) requires an unsigned integer given in the argument list.\n", errout.str());
} }
void testMicrosoftPrintfArgument() { void testMicrosoftPrintfArgument() {