CheckIO: Improved handling of h, hh, l, and ll.
This commit is contained in:
parent
464dccc188
commit
20f81f92d9
|
@ -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;
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue