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)
// 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+1 != formatString.end() && !isalpha(*(i+2))) {
if (i+1 != formatString.end()) {
if (!isalpha(*(i+2))) {
std::string modifier;
modifier += *i;
modifier += *(i+1);
invalidLengthModifierError(tok, numFormat, modifier);
done = true;
} else {
specifier = *i++;
specifier += *i++;
}
} else {
if (i != formatString.end() && !isalpha(*(i+1))) {
done = true;
}
} else {
if (i != formatString.end()) {
if (!isalpha(*(i+1))) {
std::string modifier;
modifier += *i;
invalidLengthModifierError(tok, numFormat, modifier);
}
}
done = true;
} else {
specifier = *i++;
}
} else {
done = true;
}
}
break;
case 'I': // Microsoft extension: I for size_t and ptrdiff_t, I32 for __int32, and I64 for __int64
if (i != formatString.end()) {
@ -659,8 +673,10 @@ void CheckIO::checkWrongPrintfScanfArguments()
std::string modifier;
modifier += *i;
invalidLengthModifierError(tok, numFormat, modifier);
}
done = true;
} else {
specifier = *i++;
}
break;
default:
done = true;

View File

@ -717,7 +717,7 @@ private:
// False positive tests
check("void foo(signed char sc, unsigned char uc, short int si, unsigned short int usi) {\n"
" printf(\"%hhx %hhd\", sc, uc);\n"
" printf(\"%hd %hi\", si, usi);\n"
" printf(\"%hd %hu\", si, usi);\n"
"}");
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: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());
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() {