CheckIO: Fix false positives for functions returning unknown types and false negatives for functions returning record types
This commit is contained in:
parent
450442287c
commit
a1b9bb0688
|
@ -594,7 +594,7 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
case 'X':
|
case 'X':
|
||||||
case 'o':
|
case 'o':
|
||||||
specifier += *i;
|
specifier += *i;
|
||||||
if (functionInfo && varTypeTok && (varTypeTok->isStandardType() || !Token::Match(varTypeTok->next(), "*|&"))) {
|
if (functionInfo && varTypeTok && ((varTypeTok->isStandardType() || functionInfo->retType) && varTypeTok->next()->str() != "*")) {
|
||||||
if (!Token::Match(varTypeTok, "bool|short|long|int|char|size_t") ||
|
if (!Token::Match(varTypeTok, "bool|short|long|int|char|size_t") ||
|
||||||
(specifier[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong())))) {
|
(specifier[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong())))) {
|
||||||
invalidPrintfArgTypeError_int(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_int(tok, numFormat, specifier);
|
||||||
|
@ -612,7 +612,7 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'i':
|
case 'i':
|
||||||
specifier += *i;
|
specifier += *i;
|
||||||
if (functionInfo && varTypeTok && (varTypeTok->isStandardType() || Token::Match(varTypeTok->next(), "*|&"))) {
|
if (functionInfo && varTypeTok && (varTypeTok->isStandardType() || functionInfo->retType) && varTypeTok->next()->str() != "*") {
|
||||||
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[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong())))) {
|
(specifier[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong())))) {
|
||||||
invalidPrintfArgTypeError_sint(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_sint(tok, numFormat, specifier);
|
||||||
|
@ -629,7 +629,7 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
specifier += *i;
|
specifier += *i;
|
||||||
if (functionInfo && varTypeTok && (varTypeTok->isStandardType() || !Token::Match(varTypeTok->next(), "*|&"))) {
|
if (functionInfo && varTypeTok && ((varTypeTok->isStandardType() || functionInfo->retType) || varTypeTok->next()->str() != "*")) {
|
||||||
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[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong())))) {
|
(specifier[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong())))) {
|
||||||
invalidPrintfArgTypeError_uint(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_uint(tok, numFormat, specifier);
|
||||||
|
@ -659,8 +659,8 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
||||||
case 'g':
|
case 'g':
|
||||||
case 'G':
|
case 'G':
|
||||||
specifier += *i;
|
specifier += *i;
|
||||||
if (functionInfo && varTypeTok && ((varTypeTok->isStandardType() && !Token::Match(varTypeTok, "float|double")) ||
|
if (functionInfo && varTypeTok && (((varTypeTok->isStandardType() || functionInfo->retType) && !Token::Match(varTypeTok, "float|double")) ||
|
||||||
Token::Match(varTypeTok->next(), "*|&") ||
|
Token::simpleMatch(varTypeTok->next(), "*") ||
|
||||||
(specifier[0] == 'l' && (!varTypeTok->isLong() || varTypeTok->str() != "double")) ||
|
(specifier[0] == 'l' && (!varTypeTok->isLong() || varTypeTok->str() != "double")) ||
|
||||||
(specifier[0] != 'l' && varTypeTok->isLong())))
|
(specifier[0] != 'l' && varTypeTok->isLong())))
|
||||||
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
|
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
|
||||||
|
|
|
@ -423,7 +423,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
|
|
||||||
// find the return type
|
// find the return type
|
||||||
if (function.type != Function::eConstructor) {
|
if (function.type != Function::eConstructor) {
|
||||||
while (tok1 && Token::Match(tok1->next(), "virtual|static|friend|const"))
|
while (tok1 && Token::Match(tok1->next(), "virtual|static|friend|const|struct|union"))
|
||||||
tok1 = tok1->next();
|
tok1 = tok1->next();
|
||||||
|
|
||||||
if (tok1)
|
if (tok1)
|
||||||
|
@ -741,6 +741,22 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
classAndStructScopes.push_back(&*it);
|
classAndStructScopes.push_back(&*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fill in function return types
|
||||||
|
for (std::list<Scope>::iterator it = scopeList.begin(); it != scopeList.end(); ++it) {
|
||||||
|
std::list<Function>::iterator func;
|
||||||
|
|
||||||
|
for (func = it->functionList.begin(); func != it->functionList.end(); ++func) {
|
||||||
|
// add return types
|
||||||
|
if (func->retDef) {
|
||||||
|
const Token *type = func->retDef;
|
||||||
|
while (Token::Match(type, "static|const|struct|union"))
|
||||||
|
type = type->next();
|
||||||
|
if (type)
|
||||||
|
func->retType = findTypeInNested(type, func->nestedIn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// determine if user defined type needs initialization
|
// determine if user defined type needs initialization
|
||||||
unsigned int unknowns = 0; // stop checking when there are no unknowns
|
unsigned int unknowns = 0; // stop checking when there are no unknowns
|
||||||
unsigned int retry = 0; // bail if we don't resolve all the variable types for some reason
|
unsigned int retry = 0; // bail if we don't resolve all the variable types for some reason
|
||||||
|
@ -1725,9 +1741,10 @@ void SymbolDatabase::printOut(const char *title) const
|
||||||
std::cout << " isDelete: " << (func->isDelete ? "true" : "false") << std::endl;
|
std::cout << " isDelete: " << (func->isDelete ? "true" : "false") << std::endl;
|
||||||
std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl;
|
std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl;
|
||||||
std::cout << " retFuncPtr: " << (func->retFuncPtr ? "true" : "false") << std::endl;
|
std::cout << " retFuncPtr: " << (func->retFuncPtr ? "true" : "false") << std::endl;
|
||||||
std::cout << " tokenDef: " << _tokenizer->list.fileLine(func->tokenDef) << std::endl;
|
std::cout << " tokenDef: " << func->tokenDef->str() << " " <<_tokenizer->list.fileLine(func->tokenDef) << std::endl;
|
||||||
std::cout << " argDef: " << _tokenizer->list.fileLine(func->argDef) << std::endl;
|
std::cout << " argDef: " << _tokenizer->list.fileLine(func->argDef) << std::endl;
|
||||||
std::cout << " retDef: " << func->retDef->str() << " " <<_tokenizer->list.fileLine(func->retDef) << std::endl;
|
std::cout << " retDef: " << func->retDef->str() << " " <<_tokenizer->list.fileLine(func->retDef) << std::endl;
|
||||||
|
std::cout << " retType: " << func->retType << std::endl;
|
||||||
if (func->hasBody) {
|
if (func->hasBody) {
|
||||||
std::cout << " token: " << _tokenizer->list.fileLine(func->token) << std::endl;
|
std::cout << " token: " << _tokenizer->list.fileLine(func->token) << std::endl;
|
||||||
std::cout << " arg: " << _tokenizer->list.fileLine(func->arg) << std::endl;
|
std::cout << " arg: " << _tokenizer->list.fileLine(func->arg) << std::endl;
|
||||||
|
|
|
@ -451,6 +451,7 @@ public:
|
||||||
token(NULL),
|
token(NULL),
|
||||||
arg(NULL),
|
arg(NULL),
|
||||||
retDef(NULL),
|
retDef(NULL),
|
||||||
|
retType(NULL),
|
||||||
functionScope(NULL),
|
functionScope(NULL),
|
||||||
nestedIn(NULL),
|
nestedIn(NULL),
|
||||||
initArgCount(0),
|
initArgCount(0),
|
||||||
|
@ -502,7 +503,8 @@ public:
|
||||||
const Token *argDef; // function argument start '(' in class definition
|
const Token *argDef; // function argument start '(' in class definition
|
||||||
const Token *token; // function name token in implementation
|
const Token *token; // function name token in implementation
|
||||||
const Token *arg; // function argument start '('
|
const Token *arg; // function argument start '('
|
||||||
const Token *retDef;
|
const Token *retDef; // function return type token
|
||||||
|
const ::Type *retType; // function return type
|
||||||
const Scope *functionScope; // scope of function body
|
const Scope *functionScope; // scope of function body
|
||||||
const Scope* nestedIn; // Scope the function is declared in
|
const Scope* nestedIn; // Scope the function is declared in
|
||||||
std::list<Variable> argumentList; // argument list
|
std::list<Variable> argumentList; // argument list
|
||||||
|
|
|
@ -9540,6 +9540,30 @@ void Tokenizer::createSymbolDatabase()
|
||||||
membertok->variable(membervar);
|
membertok->variable(membervar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for function returning record type
|
||||||
|
// func(...).var
|
||||||
|
// func(...)[...].var
|
||||||
|
else if (tok->function() && tok->next()->str() == "(" &&
|
||||||
|
(Token::Match(tok->next()->link(), ") . %var% !!(") ||
|
||||||
|
(Token::Match(tok->next()->link(), ") [") && Token::Match(tok->next()->link()->next()->link(), "] . %var% !!(")))) {
|
||||||
|
const Type *type = tok->function()->retType;
|
||||||
|
if (type) {
|
||||||
|
Token *membertok;
|
||||||
|
if (tok->next()->link()->next()->str() == ".")
|
||||||
|
membertok = tok->next()->link()->next()->next();
|
||||||
|
else
|
||||||
|
membertok = tok->next()->link()->next()->link()->next()->next();
|
||||||
|
const Variable *membervar = membertok->variable();
|
||||||
|
if (!membervar) {
|
||||||
|
if (type->classScope) {
|
||||||
|
membervar = type->classScope->getVariable(membertok->str());
|
||||||
|
if (membervar)
|
||||||
|
membertok->variable(membervar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
198
test/testio.cpp
198
test/testio.cpp
|
@ -861,93 +861,93 @@ private:
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
check("int f() { return 0; }\n"
|
check("int f() { return 0; }\n"
|
||||||
"void foo() { printf(\"%u %lu %f %lf %p\", f(), f(), f(), f(), f()); }");
|
"void foo() { printf(\"%d %u %lu %f %lf %p\", f(), f(), f(), f(), f(), f()); }");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lu in format string (no. 2) requires an unsigned long integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lu in format string (no. 3) requires an unsigned long integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
check("unsigned int f() { return 0; }\n"
|
check("unsigned int f() { return 0; }\n"
|
||||||
"void foo() { printf(\"%d %ld %f %lf %p\", f(), f(), f(), f(), f()); }");
|
"void foo() { printf(\"%u %d %ld %f %lf %p\", f(), f(), f(), f(), f(), f()); }");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %ld in format string (no. 2) requires a signed long integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
check("long f() { return 0; }\n"
|
check("long f() { return 0; }\n"
|
||||||
"void foo() { printf(\"%u %f %lf %p\", f(), f(), f(), f()); }");
|
"void foo() { printf(\"%ld %u %f %lf %p\", f(), f(), f(), f(), f()); }");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %f in format string (no. 2) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lf in format string (no. 3) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 4) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
check("unsigned long f() { return 0; }\n"
|
check("unsigned long f() { return 0; }\n"
|
||||||
"void foo() { printf(\"%d %f %lf %p\", f(), f(), f(), f()); }");
|
"void foo() { printf(\"%lu %d %f %lf %p\", f(), f(), f(), f(), f()); }");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %f in format string (no. 2) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lf in format string (no. 3) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 4) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
check("float f() { return 0; }\n"
|
check("float f() { return 0; }\n"
|
||||||
"void foo() { printf(\"%d %ld %u %lu %lf %p\", f(), f(), f(), f(), f(), f()); }");
|
"void foo() { printf(\"%f %d %ld %u %lu %lf %p\", f(), f(), f(), f(), f(), f(), f()); }");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %ld in format string (no. 2) requires a signed long integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %u in format string (no. 3) requires an unsigned integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %u in format string (no. 4) requires an unsigned integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lu in format string (no. 4) requires an unsigned long integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lu in format string (no. 5) requires an unsigned long integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lf in format string (no. 6) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:2]: (warning) %p in format string (no. 7) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
check("double f() { return 0; }\n"
|
check("double f() { return 0; }\n"
|
||||||
"void foo() { printf(\"%d %ld %u %lu %lf %p\", f(), f(), f(), f(), f(), f()); }");
|
"void foo() { printf(\"%f %d %ld %u %lu %lf %p\", f(), f(), f(), f(), f(), f(), f()); }");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %ld in format string (no. 2) requires a signed long integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %u in format string (no. 3) requires an unsigned integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %u in format string (no. 4) requires an unsigned integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lu in format string (no. 4) requires an unsigned long integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lu in format string (no. 5) requires an unsigned long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:2]: (warning) %lf in format string (no. 6) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:2]: (warning) %p in format string (no. 7) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
|
check("long double f() { return 0; }\n"
|
||||||
|
"void foo() { printf(\"%lf %d %ld %u %lu %f %p\", f(), f(), f(), f(), f(), f(), f()); }");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer given in the argument list.\n"
|
||||||
|
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:2]: (warning) %u in format string (no. 4) requires an unsigned integer given in the argument list.\n"
|
||||||
|
"[test.cpp:2]: (warning) %lu in format string (no. 5) requires an unsigned long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:2]: (warning) %f in format string (no. 6) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:2]: (warning) %p in format string (no. 7) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
|
check("namespace bar { int f() { return 0; } }\n"
|
||||||
|
"void foo() { printf(\"%d %u %lu %f %lf %p\", bar::f(), bar::f(), bar::f(), bar::f(), bar::f(), bar::f()); }");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
|
||||||
|
"[test.cpp:2]: (warning) %lu in format string (no. 3) requires an unsigned long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:2]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
check("long double f() { return 0; }\n"
|
check("struct Fred { int i; } f;\n"
|
||||||
"void foo() { printf(\"%d %ld %u %lu %f %p\", f(), f(), f(), f(), f(), f()); }");
|
"void foo() { printf(\"%d %u %lu %f %lf %p\", f.i, f.i, f.i, f.i, f.i, f.i); }");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %ld in format string (no. 2) requires a signed long integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lu in format string (no. 3) requires an unsigned long integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %u in format string (no. 3) requires an unsigned integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lu in format string (no. 4) requires an unsigned long integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %f in format string (no. 5) requires a floating point number given in the argument list.\n"
|
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
check("namespace bar { int f() { return 0; } }\n"
|
|
||||||
"void foo() { printf(\"%u %lu %f %lf %p\", bar::f(), bar::f(), bar::f(), bar::f(), bar::f()); }");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n"
|
|
||||||
"[test.cpp:2]: (warning) %lu in format string (no. 2) requires an unsigned long integer given in the argument list.\n"
|
|
||||||
"[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n"
|
|
||||||
"[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n"
|
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str());
|
|
||||||
|
|
||||||
check("struct Fred { int i; } f;\n"
|
|
||||||
"void foo() { printf(\"%u %lu %f %lf %p\", f.i, f.i, f.i, f.i, f.i); }");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n"
|
|
||||||
"[test.cpp:2]: (warning) %lu in format string (no. 2) requires an unsigned long integer given in the argument list.\n"
|
|
||||||
"[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n"
|
|
||||||
"[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n"
|
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str());
|
|
||||||
|
|
||||||
check("struct Fred { unsigned int u; } f;\n"
|
check("struct Fred { unsigned int u; } f;\n"
|
||||||
"void foo() { printf(\"%d %ld %f %lf %p\", f.u, f.u, f.u, f.u, f.u); }");
|
"void foo() { printf(\"%u %d %ld %f %lf %p\", f.u, f.u, f.u, f.u, f.u, f.u); }");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %ld in format string (no. 2) requires a signed long integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
check("struct Fred { unsigned int ui() { return 0; } } f;\n"
|
check("struct Fred { unsigned int ui() { return 0; } } f;\n"
|
||||||
"void foo() { printf(\"%d %ld %f %lf %p\", f.ui(), f.ui(), f.ui(), f.ui(), f.ui()); }");
|
"void foo() { printf(\"%u %d %ld %f %lf %p\", f.ui(), f.ui(), f.ui(), f.ui(), f.ui(), f.ui()); }");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
|
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %ld in format string (no. 2) requires a signed long integer given in the argument list.\n"
|
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %lf in format string (no. 4) requires a floating point number given in the argument list.\n"
|
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
"[test.cpp:2]: (warning) %p in format string (no. 5) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
// #4975
|
// #4975
|
||||||
check("void f(int len, int newline) {\n"
|
check("void f(int len, int newline) {\n"
|
||||||
|
@ -955,6 +955,66 @@ private:
|
||||||
" printf(\"%s\", newline + newline);\n"
|
" printf(\"%s\", newline + newline);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("struct Fred { int i; } f;\n"
|
||||||
|
"struct Fred & bar() { };\n"
|
||||||
|
"void foo() { printf(\"%d %u %lu %f %lf %p\", bar().i, bar().i, bar().i, bar().i, bar().i, bar().i); }");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
|
check("struct Fred { int i; } f;\n"
|
||||||
|
"const struct Fred & bar() { };\n"
|
||||||
|
"void foo() { printf(\"%d %u %lu %f %lf %p\", bar().i, bar().i, bar().i, bar().i, bar().i, bar().i); }");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
|
check("struct Fred { int i; } f;\n"
|
||||||
|
"static const struct Fred & bar() { };\n"
|
||||||
|
"void foo() { printf(\"%d %u %lu %f %lf %p\", bar().i, bar().i, bar().i, bar().i, bar().i, bar().i); }");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
|
check("struct Fred { int i; } f[2];\n"
|
||||||
|
"struct Fred * bar() { return f; };\n"
|
||||||
|
"void foo() { printf(\"%d %u %lu %f %lf %p\", bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i); }");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
|
check("struct Fred { int i; } f[2];\n"
|
||||||
|
"const struct Fred * bar() { return f; };\n"
|
||||||
|
"void foo() { printf(\"%d %u %lu %f %lf %p\", bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i); }");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
|
check("struct Fred { int i; } f[2];\n"
|
||||||
|
"static const struct Fred * bar() { return f; };\n"
|
||||||
|
"void foo() { printf(\"%d %u %lu %f %lf %p\", bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i); }");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number given in the argument list.\n"
|
||||||
|
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
|
||||||
|
|
||||||
|
check("struct Fred { int32_t i; } f;\n"
|
||||||
|
"struct Fred & bar() { };\n"
|
||||||
|
"void foo() { printf(\"%d %ld %u %lu %f %lf\", bar().i, bar().i, bar().i, bar().i, bar().i, bar().i); }");
|
||||||
|
ASSERT_EQUALS("", 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