Fixed #4948 (check printf %l and %ll arguments for long and long long)
This commit is contained in:
parent
64733d9e63
commit
5aa79198e6
|
@ -591,36 +591,38 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
case 'o':
|
case 'o':
|
||||||
if (varTypeTok && isKnownType(variableInfo, varTypeTok) && !Token::Match(varTypeTok, "bool|short|long|int|char|size_t") && !variableInfo->isPointer() && !variableInfo->isArray()) {
|
specifier += *i;
|
||||||
specifier += *i;
|
if (varTypeTok && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
|
||||||
invalidPrintfArgTypeError_int(tok, numFormat, specifier);
|
if (!Token::Match(varTypeTok, "bool|short|long|int|char|size_t") ||
|
||||||
|
(specifier[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong())))) {
|
||||||
|
invalidPrintfArgTypeError_int(tok, numFormat, specifier);
|
||||||
|
}
|
||||||
} else if (argListTok->type() == Token::eString) {
|
} else if (argListTok->type() == Token::eString) {
|
||||||
specifier += *i;
|
|
||||||
invalidPrintfArgTypeError_int(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_int(tok, numFormat, specifier);
|
||||||
}
|
}
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
case 'i':
|
||||||
|
specifier += *i;
|
||||||
if (varTypeTok && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
|
if (varTypeTok && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
|
||||||
if ((varTypeTok->isUnsigned() || !Token::Match(varTypeTok, "bool|short|long|int")) && varTypeTok->str() != "char") {
|
if (((varTypeTok->isUnsigned() || !Token::Match(varTypeTok, "bool|short|long|int")) && varTypeTok->str() != "char") ||
|
||||||
specifier += *i;
|
(specifier[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong())))) {
|
||||||
invalidPrintfArgTypeError_sint(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_sint(tok, numFormat, specifier);
|
||||||
}
|
}
|
||||||
} else if (argListTok->type() == Token::eString) {
|
} else if (argListTok->type() == Token::eString) {
|
||||||
specifier += *i;
|
|
||||||
invalidPrintfArgTypeError_sint(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_sint(tok, numFormat, specifier);
|
||||||
}
|
}
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
|
specifier += *i;
|
||||||
if (varTypeTok && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
|
if (varTypeTok && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
|
||||||
if ((!varTypeTok->isUnsigned() || !Token::Match(varTypeTok, "char|short|long|int|size_t")) && varTypeTok->str() != "bool") {
|
if (((!varTypeTok->isUnsigned() || !Token::Match(varTypeTok, "char|short|long|int|size_t")) && varTypeTok->str() != "bool") ||
|
||||||
specifier += *i;
|
(specifier[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong())))) {
|
||||||
invalidPrintfArgTypeError_uint(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_uint(tok, numFormat, specifier);
|
||||||
}
|
}
|
||||||
} else if (argListTok->type() == Token::eString) {
|
} else if (argListTok->type() == Token::eString) {
|
||||||
specifier += *i;
|
|
||||||
invalidPrintfArgTypeError_uint(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_uint(tok, numFormat, specifier);
|
||||||
}
|
}
|
||||||
done = true;
|
done = true;
|
||||||
|
@ -803,19 +805,29 @@ void CheckIO::invalidPrintfArgTypeError_p(const Token* tok, unsigned int numForm
|
||||||
void CheckIO::invalidPrintfArgTypeError_int(const Token* tok, unsigned int numFormat, const std::string& specifier)
|
void CheckIO::invalidPrintfArgTypeError_int(const Token* tok, unsigned int numFormat, const std::string& specifier)
|
||||||
{
|
{
|
||||||
std::ostringstream errmsg;
|
std::ostringstream errmsg;
|
||||||
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires an integer given in the argument list.";
|
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires a"
|
||||||
|
<< (specifier[0] != 'l' ? "n" : "")
|
||||||
|
<< (specifier[0] == 'l' ? " long" : "")
|
||||||
|
<< (specifier[0] == 'l' && specifier[1] == 'l' ? " long" : "")
|
||||||
|
<< " integer given in the argument list.";
|
||||||
reportError(tok, Severity::warning, "invalidPrintfArgType_int", errmsg.str());
|
reportError(tok, Severity::warning, "invalidPrintfArgType_int", errmsg.str());
|
||||||
}
|
}
|
||||||
void CheckIO::invalidPrintfArgTypeError_uint(const Token* tok, unsigned int numFormat, const std::string& specifier)
|
void CheckIO::invalidPrintfArgTypeError_uint(const Token* tok, unsigned int numFormat, const std::string& specifier)
|
||||||
{
|
{
|
||||||
std::ostringstream errmsg;
|
std::ostringstream errmsg;
|
||||||
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires an unsigned integer given in the argument list.";
|
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires an unsigned "
|
||||||
|
<< (specifier[0] == 'l' ? "long " : "")
|
||||||
|
<< (specifier[0] == 'l' && specifier[1] == 'l' ? "long " : "")
|
||||||
|
<< "integer given in the argument list.";
|
||||||
reportError(tok, Severity::warning, "invalidPrintfArgType_uint", errmsg.str());
|
reportError(tok, Severity::warning, "invalidPrintfArgType_uint", errmsg.str());
|
||||||
}
|
}
|
||||||
void CheckIO::invalidPrintfArgTypeError_sint(const Token* tok, unsigned int numFormat, const std::string& specifier)
|
void CheckIO::invalidPrintfArgTypeError_sint(const Token* tok, unsigned int numFormat, const std::string& specifier)
|
||||||
{
|
{
|
||||||
std::ostringstream errmsg;
|
std::ostringstream errmsg;
|
||||||
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires a signed integer given in the argument list.";
|
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires a signed "
|
||||||
|
<< (specifier[0] == 'l' ? "long " : "")
|
||||||
|
<< (specifier[0] == 'l' && specifier[1] == 'l' ? "long " : "")
|
||||||
|
<< "integer given in the argument list.";
|
||||||
reportError(tok, Severity::warning, "invalidPrintfArgType_sint", errmsg.str());
|
reportError(tok, Severity::warning, "invalidPrintfArgType_sint", errmsg.str());
|
||||||
}
|
}
|
||||||
void CheckIO::invalidPrintfArgTypeError_float(const Token* tok, unsigned int numFormat, const std::string& specifier)
|
void CheckIO::invalidPrintfArgTypeError_float(const Token* tok, unsigned int numFormat, const std::string& specifier)
|
||||||
|
|
|
@ -769,8 +769,8 @@ private:
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %hd in format string (no. 1) requires a signed integer given in the argument list.\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: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:4]: (warning) %ld in format string (no. 1) requires a signed long 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());
|
"[test.cpp:5]: (warning) %lld in format string (no. 1) requires a signed long long integer given in the argument list.\n" , errout.str());
|
||||||
|
|
||||||
check("void foo(size_t s, ptrdiff_t p) {\n"
|
check("void foo(size_t s, ptrdiff_t p) {\n"
|
||||||
" printf(\"%zd\", s);\n"
|
" printf(\"%zd\", s);\n"
|
||||||
|
@ -779,6 +779,20 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %zd in format string (no. 1) requires a signed integer given in the argument list.\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());
|
"[test.cpp:3]: (warning) %tu in format string (no. 1) requires an unsigned integer given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo(unsigned int i) {\n"
|
||||||
|
" printf(\"%ld\", i);\n"
|
||||||
|
" printf(\"%lld\", i);\n"
|
||||||
|
" printf(\"%lu\", i);\n"
|
||||||
|
" printf(\"%llu\", i);\n"
|
||||||
|
" printf(\"%lx\", i);\n"
|
||||||
|
" printf(\"%llx\", i);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %ld in format string (no. 1) requires a signed long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lld in format string (no. 1) requires a signed long long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:4]: (warning) %lu in format string (no. 1) requires an unsigned long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:5]: (warning) %llu in format string (no. 1) requires an unsigned long long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:6]: (warning) %lx in format string (no. 1) requires a long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:7]: (warning) %llx in format string (no. 1) requires a long long integer given in the argument list.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPosixPrintfScanfParameterPosition() { // #4900 - No support for parameters in format strings
|
void testPosixPrintfScanfParameterPosition() { // #4900 - No support for parameters in format strings
|
||||||
|
|
Loading…
Reference in New Issue