CheckIO: improved type info - keep track of original typename.

This commit is contained in:
Robert Reif 2013-08-31 06:26:39 +02:00 committed by Daniel Marjamäki
parent 92b7280d13
commit 05f2f0e419
7 changed files with 482 additions and 268 deletions

View File

@ -561,7 +561,7 @@ void CheckIO::checkWrongPrintfScanfArguments()
bool element;
if (getArgumentInfo(argListTok, &variableInfo, &varTypeTok, &functionInfo, element)) {
if (varTypeTok && varTypeTok->str() == "static")
if (varTypeTok->str() == "static")
varTypeTok = varTypeTok->next();
if (scan && varTypeTok) {
@ -586,7 +586,7 @@ void CheckIO::checkWrongPrintfScanfArguments()
done = true;
break;
case 'n':
if ((varTypeTok && isKnownType(variableInfo, varTypeTok) && ((!variableInfo->isPointer() && !variableInfo->isArray()) || varTypeTok->strAt(-1) == "const")) || argListTok->type() == Token::eString)
if ((variableInfo && isKnownType(variableInfo, varTypeTok) && ((!variableInfo->isPointer() && !variableInfo->isArray()) || varTypeTok->strAt(-1) == "const")) || argListTok->type() == Token::eString)
invalidPrintfArgTypeError_n(tok, numFormat);
done = true;
break;
@ -595,69 +595,69 @@ void CheckIO::checkWrongPrintfScanfArguments()
case 'X':
case 'o':
specifier += *i;
if (functionInfo && varTypeTok && ((varTypeTok->isStandardType() || functionInfo->retType) && varTypeTok->next()->str() != "*")) {
if (functionInfo && ((varTypeTok->isStandardType() || functionInfo->retType) && varTypeTok->next()->str() != "*")) {
if (!Token::Match(varTypeTok, "bool|short|long|int|char|size_t") ||
(specifier[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong()))) ||
(specifier.find("I64") != std::string::npos && (varTypeTok->str() != "long" || !varTypeTok->isLong()))) {
invalidPrintfArgTypeError_int(tok, numFormat, specifier);
invalidPrintfArgTypeError_int(tok, numFormat, specifier, varTypeTok);
}
} else if (variableInfo && varTypeTok && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
} else if (variableInfo && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
if (!Token::Match(varTypeTok, "bool|short|long|int|char|size_t") ||
(specifier[0] == 'l' && (varTypeTok->str() != "long" || (specifier[1] == 'l' && !varTypeTok->isLong()))) ||
(specifier.find("I64") != std::string::npos && (varTypeTok->str() != "long" || !varTypeTok->isLong()))) {
invalidPrintfArgTypeError_int(tok, numFormat, specifier);
invalidPrintfArgTypeError_int(tok, numFormat, specifier, varTypeTok);
}
} else if (argListTok->type() == Token::eString) {
invalidPrintfArgTypeError_int(tok, numFormat, specifier);
} else if (varTypeTok->type() == Token::eString) {
invalidPrintfArgTypeError_int(tok, numFormat, specifier, varTypeTok);
}
done = true;
break;
case 'd':
case 'i':
specifier += *i;
if (functionInfo && varTypeTok && (varTypeTok->isStandardType() || functionInfo->retType) && varTypeTok->next()->str() != "*") {
if (functionInfo && (varTypeTok->isStandardType() || functionInfo->retType) && varTypeTok->next()->str() != "*") {
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.find("I64") != std::string::npos && (varTypeTok->str() != "long" || !varTypeTok->isLong()))) {
invalidPrintfArgTypeError_sint(tok, numFormat, specifier);
invalidPrintfArgTypeError_sint(tok, numFormat, specifier, varTypeTok);
}
} else if (variableInfo && varTypeTok && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
} else if (variableInfo && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
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.find("I64") != std::string::npos && (varTypeTok->str() != "long" || !varTypeTok->isLong()))) {
invalidPrintfArgTypeError_sint(tok, numFormat, specifier);
invalidPrintfArgTypeError_sint(tok, numFormat, specifier, varTypeTok);
}
} else if (argListTok->type() == Token::eString) {
invalidPrintfArgTypeError_sint(tok, numFormat, specifier);
} else if (varTypeTok->type() == Token::eString) {
invalidPrintfArgTypeError_sint(tok, numFormat, specifier, varTypeTok);
}
done = true;
break;
case 'u':
specifier += *i;
if (functionInfo && varTypeTok && ((varTypeTok->isStandardType() || functionInfo->retType) || varTypeTok->next()->str() != "*")) {
if (functionInfo && ((varTypeTok->isStandardType() || functionInfo->retType) || varTypeTok->next()->str() != "*")) {
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.find("I64") != std::string::npos && (varTypeTok->str() != "long" || !varTypeTok->isLong()))) {
invalidPrintfArgTypeError_uint(tok, numFormat, specifier);
invalidPrintfArgTypeError_uint(tok, numFormat, specifier, varTypeTok);
}
} else if (variableInfo && varTypeTok && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
} else if (variableInfo && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray()) {
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.find("I64") != std::string::npos && (varTypeTok->str() != "long" || !varTypeTok->isLong()))) {
invalidPrintfArgTypeError_uint(tok, numFormat, specifier);
invalidPrintfArgTypeError_uint(tok, numFormat, specifier, varTypeTok);
}
} else if (argListTok->type() == Token::eString) {
invalidPrintfArgTypeError_uint(tok, numFormat, specifier);
} else if (varTypeTok->type() == Token::eString) {
invalidPrintfArgTypeError_uint(tok, numFormat, specifier, varTypeTok);
}
done = true;
break;
case 'p':
if (functionInfo && varTypeTok && varTypeTok->type() == Token::eType && varTypeTok->next()->str() != "*")
invalidPrintfArgTypeError_p(tok, numFormat);
if (functionInfo && varTypeTok->type() == Token::eType && varTypeTok->next()->str() != "*")
invalidPrintfArgTypeError_p(tok, numFormat, varTypeTok);
else if (variableInfo && varTypeTok && isKnownType(variableInfo, varTypeTok) && !variableInfo->isPointer() && !variableInfo->isArray())
invalidPrintfArgTypeError_p(tok, numFormat);
else if (argListTok->type() == Token::eString)
invalidPrintfArgTypeError_p(tok, numFormat);
invalidPrintfArgTypeError_p(tok, numFormat, varTypeTok);
else if (varTypeTok->type() == Token::eString)
invalidPrintfArgTypeError_p(tok, numFormat, varTypeTok);
done = true;
break;
case 'e':
@ -666,18 +666,18 @@ void CheckIO::checkWrongPrintfScanfArguments()
case 'g':
case 'G':
specifier += *i;
if (functionInfo && varTypeTok && (((varTypeTok->isStandardType() || functionInfo->retType) && !Token::Match(varTypeTok, "float|double")) ||
(!element && Token::simpleMatch(varTypeTok->next(), "*")) ||
(element && !Token::simpleMatch(varTypeTok->next(), "*")) ||
(specifier[0] == 'l' && (!varTypeTok->isLong() || varTypeTok->str() != "double")) ||
(specifier[0] != 'l' && varTypeTok->isLong())))
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
else if (variableInfo && varTypeTok && ((isKnownType(variableInfo, varTypeTok) && !Token::Match(varTypeTok, "float|double")) ||
(!element && variableInfo->isArrayOrPointer()) ||
(element && !variableInfo->isArrayOrPointer())))
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
else if (argListTok->type() == Token::eString)
invalidPrintfArgTypeError_float(tok, numFormat, specifier);
if (functionInfo && (((varTypeTok->isStandardType() || functionInfo->retType) && !Token::Match(varTypeTok, "float|double")) ||
(!element && Token::simpleMatch(varTypeTok->next(), "*")) ||
(element && !Token::simpleMatch(varTypeTok->next(), "*")) ||
(specifier[0] == 'l' && (!varTypeTok->isLong() || varTypeTok->str() != "double")) ||
(specifier[0] != 'l' && varTypeTok->isLong())))
invalidPrintfArgTypeError_float(tok, numFormat, specifier, varTypeTok);
else if (variableInfo && ((isKnownType(variableInfo, varTypeTok) && !Token::Match(varTypeTok, "float|double")) ||
(!element && variableInfo->isArrayOrPointer()) ||
(element && !variableInfo->isArrayOrPointer())))
invalidPrintfArgTypeError_float(tok, numFormat, specifier, varTypeTok);
else if (varTypeTok->type() == Token::eString)
invalidPrintfArgTypeError_float(tok, numFormat, specifier, varTypeTok);
done = true;
break;
case 'h': // Can be 'hh' (signed char or unsigned char) or 'h' (short int or unsigned short int)
@ -775,7 +775,7 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok
if (tok) {
if (tok->type() == Token::eString) {
*var = 0;
*typeTok = 0;
*typeTok = tok;
*func = 0;
element = false;
return true;
@ -824,6 +824,7 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok
const Variable *variableInfo = varTok->variable();
*var = variableInfo;
element = tok1->previous()->str() == "]";
*func = 0;
// look for std::vector operator [] and use template type as return type
if (variableInfo) {
@ -833,9 +834,8 @@ bool CheckIO::getArgumentInfo(const Token * tok, const Variable **var, const Tok
} else
*typeTok = variableInfo->typeStartToken();
} else
*typeTok = NULL;
return false;
*func = 0;
return true;
}
}
@ -896,23 +896,63 @@ void CheckIO::invalidPrintfArgTypeError_n(const Token* tok, unsigned int numForm
errmsg << "%n in format string (no. " << numFormat << ") requires a pointer to an non-const integer given in the argument list.";
reportError(tok, Severity::warning, "invalidPrintfArgType_n", errmsg.str());
}
void CheckIO::invalidPrintfArgTypeError_p(const Token* tok, unsigned int numFormat)
void CheckIO::invalidPrintfArgTypeError_p(const Token* tok, unsigned int numFormat, const Token* type)
{
std::ostringstream errmsg;
errmsg << "%p in format string (no. " << numFormat << ") requires an address given in the argument list.";
errmsg << "%p in format string (no. " << numFormat << ") requires an address but the argument type is \'";
if (type) {
if (type->type() == Token::eString) {
if (type->isLong())
errmsg << "const wchar_t *";
else
errmsg << "const char *";
} else {
type->stringify(errmsg, false, true);
if (type->strAt(1) == "*")
errmsg << " *";
}
} else
errmsg << "Unknown";
errmsg << "\'.";
reportError(tok, Severity::warning, "invalidPrintfArgType_p", errmsg.str());
}
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, const Token* type)
{
std::ostringstream errmsg;
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.";
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires a";
if (specifier.find("I64") != std::string::npos)
errmsg << " long long ";
else
errmsg << (specifier[0] == 'l' ? " long " : "n ")
<< (specifier[0] == 'l' && specifier[1] == 'l' ? "long " : "");
errmsg << "integer but the argument type is \'";
if (type) {
if (type->type() == Token::eString) {
if (type->isLong())
errmsg << "const wchar_t *";
else
errmsg << "const char *";
} else {
if (type->originalName().empty()) {
type->stringify(errmsg, false, true);
if (type->strAt(1) == "*")
errmsg << " *";
} else {
if ((type->originalName() == "__int64" || type->originalName() == "__int32") && type->isUnsigned())
errmsg << "unsigned ";
errmsg << type->originalName() << " {aka ";
type->stringify(errmsg, false, true);
if (type->strAt(1) == "*")
errmsg << " *";
errmsg << "}";
}
}
} else
errmsg << "Unknown";
errmsg << "\'.";
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, const Token* type)
{
std::ostringstream errmsg;
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires an unsigned ";
@ -921,10 +961,34 @@ void CheckIO::invalidPrintfArgTypeError_uint(const Token* tok, unsigned int numF
else
errmsg << (specifier[0] == 'l' ? "long " : "")
<< (specifier[0] == 'l' && specifier[1] == 'l' ? "long " : "");
errmsg << "integer given in the argument list.";
errmsg << "integer but the argument type is \'";
if (type) {
if (type->type() == Token::eString) {
if (type->isLong())
errmsg << "const wchar_t *";
else
errmsg << "const char *";
} else {
if (type->originalName().empty()) {
type->stringify(errmsg, false, true);
if (type->strAt(1) == "*")
errmsg << " *";
} else {
if ((type->originalName() == "__int64" || type->originalName() == "__int32") && type->isUnsigned())
errmsg << "unsigned ";
errmsg << type->originalName() << " {aka ";
type->stringify(errmsg, false, true);
if (type->strAt(1) == "*")
errmsg << " *";
errmsg << "}";
}
}
} else
errmsg << "Unknown";
errmsg << "\'.";
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, const Token* type)
{
std::ostringstream errmsg;
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires a signed ";
@ -933,13 +997,61 @@ void CheckIO::invalidPrintfArgTypeError_sint(const Token* tok, unsigned int numF
else
errmsg << (specifier[0] == 'l' ? "long " : "")
<< (specifier[0] == 'l' && specifier[1] == 'l' ? "long " : "");
errmsg << "integer given in the argument list.";
errmsg << "integer but the argument type is \'";
if (type) {
if (type->type() == Token::eString) {
if (type->isLong())
errmsg << "const wchar_t *";
else
errmsg << "const char *";
} else {
if (type->originalName().empty()) {
type->stringify(errmsg, false, true);
if (type->strAt(1) == "*")
errmsg << " *";
} else {
if ((type->originalName() == "__int64" || type->originalName() == "__int32") && type->isUnsigned())
errmsg << "unsigned ";
errmsg << type->originalName() << " {aka ";
type->stringify(errmsg, false, true);
if (type->strAt(1) == "*")
errmsg << " *";
errmsg << "}";
}
}
} else
errmsg << "Unknown";
errmsg << "\'.";
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, const Token* type)
{
std::ostringstream errmsg;
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires a floating point number given in the argument list.";
errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires a floating point number but the argument type is \'";
if (type) {
if (type->type() == Token::eString) {
if (type->isLong())
errmsg << "const wchar_t *";
else
errmsg << "const char *";
} else {
if (type->originalName().empty()) {
type->stringify(errmsg, false, true);
if (type->strAt(1) == "*")
errmsg << " *";
} else {
if ((type->originalName() == "__int64" || type->originalName() == "__int32") && type->isUnsigned())
errmsg << "unsigned ";
errmsg << type->originalName() << " {aka ";
type->stringify(errmsg, false, true);
if (type->strAt(1) == "*")
errmsg << " *";
errmsg << "}";
}
}
} else
errmsg << "Unknown";
errmsg << "\'.";
reportError(tok, Severity::warning, "invalidPrintfArgType_float", errmsg.str());
}
void CheckIO::invalidLengthModifierError(const Token* tok, unsigned int numFormat, const std::string& modifier)

View File

@ -89,11 +89,11 @@ private:
void invalidScanfArgTypeError(const Token* tok, const std::string &functionName, unsigned int numFormat);
void invalidPrintfArgTypeError_s(const Token* tok, unsigned int numFormat);
void invalidPrintfArgTypeError_n(const Token* tok, unsigned int numFormat);
void invalidPrintfArgTypeError_p(const Token* tok, unsigned int numFormat);
void invalidPrintfArgTypeError_int(const Token* tok, unsigned int numFormat, const std::string& specifier);
void invalidPrintfArgTypeError_uint(const Token* tok, unsigned int numFormat, const std::string& specifier);
void invalidPrintfArgTypeError_sint(const Token* tok, unsigned int numFormat, const std::string& specifier);
void invalidPrintfArgTypeError_float(const Token* tok, unsigned int numFormat, const std::string& specifier);
void invalidPrintfArgTypeError_p(const Token* tok, unsigned int numFormat, const Token* type);
void invalidPrintfArgTypeError_int(const Token* tok, unsigned int numFormat, const std::string& specifier, const Token* type);
void invalidPrintfArgTypeError_uint(const Token* tok, unsigned int numFormat, const std::string& specifier, const Token* type);
void invalidPrintfArgTypeError_sint(const Token* tok, unsigned int numFormat, const std::string& specifier, const Token* type);
void invalidPrintfArgTypeError_float(const Token* tok, unsigned int numFormat, const std::string& specifier, const Token* type);
void invalidLengthModifierError(const Token* tok, unsigned int numFormat, const std::string& modifier);
void invalidScanfFormatWidthError(const Token* tok, unsigned int numFormat, int width, const Variable *var);
@ -111,11 +111,11 @@ private:
c.invalidScanfArgTypeError(0, "scanf", 1);
c.invalidPrintfArgTypeError_s(0, 1);
c.invalidPrintfArgTypeError_n(0, 1);
c.invalidPrintfArgTypeError_p(0, 1);
c.invalidPrintfArgTypeError_int(0, 1, "X");
c.invalidPrintfArgTypeError_uint(0, 1, "u");
c.invalidPrintfArgTypeError_sint(0, 1, "i");
c.invalidPrintfArgTypeError_float(0, 1, "f");
c.invalidPrintfArgTypeError_p(0, 1, NULL);
c.invalidPrintfArgTypeError_int(0, 1, "X", NULL);
c.invalidPrintfArgTypeError_uint(0, 1, "u", NULL);
c.invalidPrintfArgTypeError_sint(0, 1, "i", NULL);
c.invalidPrintfArgTypeError_float(0, 1, "f", NULL);
c.invalidScanfFormatWidthError(0, 10, 5, NULL);
c.wrongPrintfScanfPosixParameterPositionError(0, "printf", 2, 1);
}

View File

@ -226,6 +226,7 @@ void Token::deleteThis()
_scope = _previous->_scope;
_function = _previous->_function;
_variable = _previous->_variable;
_originalName = _previous->_originalName;
if (_link)
_link->link(this);
@ -991,8 +992,12 @@ void Token::stringify(std::ostream& os, bool varid, bool attributes) const
os << "unsigned ";
else if (isSigned())
os << "signed ";
if (isLong())
os << "long ";
if (isLong()) {
if (_type == eString)
os << "L";
else
os << "long ";
}
}
if (_str[0] != '\"' || _str.find("\0") == std::string::npos)
os << _str;

View File

@ -557,6 +557,20 @@ public:
const Token* findClosingBracket() const;
Token* findClosingBracket();
/**
* Returns the original name.
*/
const std::string & originalName() const {
return _originalName;
}
/**
* Sets the original name.
*/
void originalName(const std::string & name) {
_originalName = name;
}
private:
void next(Token *nextToken) {
_next = nextToken;
@ -630,6 +644,10 @@ private:
Token *_astOperand1;
Token *_astOperand2;
Token *_astParent;
// original name like size_t
std::string _originalName;
public:
void astOperand1(Token *tok);
void astOperand2(Token *tok);

View File

@ -5341,9 +5341,12 @@ void Tokenizer::simplifyPlatformTypes()
enum { isLongLong, isLong, isInt } type;
/** @todo This assumes a flat address space. Not true for segmented address space (FAR *). */
if (_settings->sizeof_size_t == 8)
type = isLongLong;
else if (_settings->sizeof_size_t == 4 && _settings->sizeof_long == 4)
if (_settings->sizeof_size_t == 8) {
if (_settings->sizeof_long == 8)
type = isLong;
else
type = isLongLong;
} else if (_settings->sizeof_size_t == 4 && _settings->sizeof_long == 4)
type = isLong;
else if (_settings->sizeof_size_t == 4)
type = isInt;
@ -5351,7 +5354,9 @@ void Tokenizer::simplifyPlatformTypes()
return;
for (Token *tok = list.front(); tok; tok = tok->next()) {
bool inStd = false;
if (Token::Match(tok, "std :: size_t|ssize_t|ptrdiff_t|intptr_t|uintptr_t")) {
inStd = true;
tok->deleteNext();
tok->deleteThis();
} else if (Token::Match(tok, ":: size_t|ssize_t|ptrdiff_t|intptr_t|uintptr_t")) {
@ -5359,6 +5364,10 @@ void Tokenizer::simplifyPlatformTypes()
}
if (Token::Match(tok, "size_t|uintptr_t")) {
if (inStd)
tok->originalName("std::" + tok->str());
else
tok->originalName(tok->str());
tok->isUnsigned(true);
switch (type) {
@ -5374,6 +5383,10 @@ void Tokenizer::simplifyPlatformTypes()
break;
}
} else if (Token::Match(tok, "ssize_t|ptrdiff_t|intptr_t")) {
if (inStd)
tok->originalName("std::" + tok->str());
else
tok->originalName(tok->str());
switch (type) {
case isLongLong:
tok->isLong(true);
@ -5393,29 +5406,41 @@ void Tokenizer::simplifyPlatformTypes()
_settings->platformType == Settings::Win32W ||
_settings->platformType == Settings::Win64) {
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "BOOL|INT|INT32|HFILE|LONG32"))
if (Token::Match(tok, "BOOL|INT|INT32|HFILE|LONG32")) {
tok->originalName(tok->str());
tok->str("int");
else if (Token::Match(tok, "BOOLEAN|BYTE|UCHAR")) {
} else if (Token::Match(tok, "BOOLEAN|BYTE|UCHAR")) {
tok->originalName(tok->str());
tok->str("char");
tok->isUnsigned(true);
} else if (tok->str() == "CHAR")
} else if (tok->str() == "CHAR") {
tok->originalName(tok->str());
tok->str("char");
else if (Token::Match(tok, "DWORD|ULONG|COLORREF|LCID|LCTYPE|LGRPID")) {
} else if (Token::Match(tok, "DWORD|ULONG|COLORREF|LCID|LCTYPE|LGRPID")) {
tok->str("long");
tok->isUnsigned(true);
} else if (Token::Match(tok, "DWORD_PTR|ULONG_PTR|SIZE_T")) {
tok->originalName(tok->str());
tok->str("long");
tok->isUnsigned(true);
if (_settings->platformType == Settings::Win64)
tok->isLong(true);
} else if (tok->str() == "FLOAT")
} else if (tok->str() == "FLOAT") {
tok->originalName(tok->str());
tok->str("float");
else if (Token::Match(tok, "HRESULT|LONG"))
} else if (Token::Match(tok, "HRESULT|LONG")) {
tok->originalName(tok->str());
tok->str("long");
else if (Token::Match(tok, "INT64|LONG64")) {
} else if (Token::Match(tok, "INT8")) {
tok->originalName(tok->str());
tok->str("char");
tok->isSigned(true);
} else if (Token::Match(tok, "INT64|LONG64|LONGLONG")) {
tok->originalName(tok->str());
tok->str("long");
tok->insertToken("long");
tok->isLong(true);
} else if (Token::Match(tok, "LONG_PTR|LPARAM|LRESULT|SSIZE_T")) {
tok->originalName(tok->str());
tok->str("long");
if (_settings->platformType == Settings::Win64)
tok->isLong(true);
@ -5461,12 +5486,15 @@ void Tokenizer::simplifyPlatformTypes()
tok->isUnsigned(true);
tok->str("short");
tok->insertToken("*");
} else if (tok->str() == "SHORT")
} else if (Token::Match(tok, "SHORT|INT16")) {
tok->originalName(tok->str());
tok->str("short");
else if (Token::Match(tok, "UINT|MMRESULT|SOCKET|ULONG32|UINT32|DWORD32")) {
} else if (Token::Match(tok, "UINT|MMRESULT|SOCKET|ULONG32|UINT32|DWORD32")) {
tok->originalName(tok->str());
tok->isUnsigned(true);
tok->str("int");
} else if (Token::Match(tok, "UINT_PTR|WPARAM")) {
tok->originalName(tok->str());
tok->isUnsigned(true);
if (_settings->platformType == Settings::Win64) {
tok->str("long");
@ -5475,17 +5503,21 @@ void Tokenizer::simplifyPlatformTypes()
tok->str("int");
}
} else if (Token::Match(tok, "USHORT|WORD|ATOM|LANGID")) {
tok->originalName(tok->str());
tok->isUnsigned(true);
tok->str("short");
} else if (tok->str() == "VOID")
} else if (tok->str() == "VOID") {
tok->originalName(tok->str());
tok->str("void");
else if (tok->str() == "TCHAR") {
} else if (tok->str() == "TCHAR") {
tok->originalName(tok->str());
if (_settings->platformType == Settings::Win32A)
tok->str("char");
else {
tok->str("wchar_t");
}
} else if (tok->str() == "TBYTE") {
tok->originalName(tok->str());
tok->isUnsigned(true);
if (_settings->platformType == Settings::Win32A)
tok->str("short");
@ -5509,6 +5541,7 @@ void Tokenizer::simplifyPlatformTypes()
tok->insertToken("wchar_t");
}
} else if (Token::Match(tok, "ULONG64|DWORD64|ULONGLONG")) {
tok->originalName(tok->str());
tok->isUnsigned(true);
tok->isLong(true);
tok->str("long");
@ -5563,13 +5596,17 @@ void Tokenizer::simplifyStdType()
tok->isSigned(!isUnsigned);
}
if (tok->str() == "__int8")
if (tok->str() == "__int8") {
tok->originalName(tok->str());
tok->str("char");
else if (tok->str() == "__int16")
} else if (tok->str() == "__int16") {
tok->originalName(tok->str());
tok->str("short");
else if (tok->str() == "__int32")
} else if (tok->str() == "__int32") {
tok->originalName(tok->str());
tok->str("int");
else if (tok->str() == "__int64") {
} else if (tok->str() == "__int64") {
tok->originalName(tok->str());
tok->str("long");
tok->isLong(true);
} else if (tok->str() == "int") {

View File

@ -647,9 +647,9 @@ private:
" printf(\"%X\", u);\n"
" printf(\"%X\", i);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) %X in format string (no. 1) requires an integer given in the argument list.\n"
"[test.cpp:4]: (warning) %c in format string (no. 1) requires an integer given in the argument list.\n"
"[test.cpp:5]: (warning) %o in format string (no. 1) requires an integer given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (warning) %X in format string (no. 1) requires an integer but the argument type is 'foo'.\n"
"[test.cpp:4]: (warning) %c in format string (no. 1) requires an integer but the argument type is 'const char *'.\n"
"[test.cpp:5]: (warning) %o in format string (no. 1) requires an integer but the argument type is 'double'.\n", errout.str());
check("class foo {};\n"
"void foo(const int* cpi, foo f, bar b, bar* bp, double d, unsigned int u, unsigned char uc) {\n"
@ -662,10 +662,10 @@ private:
" printf(\"%i\", bp);\n"
" printf(\"%i\", uc);\n" // char is smaller than int, so there shouldn't be a problem
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) %i in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:4]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:5]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:6]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (warning) %i in format string (no. 1) requires a signed integer but the argument type is 'foo'.\n"
"[test.cpp:4]: (warning) %d in format string (no. 1) requires a signed integer but the argument type is 'const char *'.\n"
"[test.cpp:5]: (warning) %d in format string (no. 1) requires a signed integer but the argument type is 'double'.\n"
"[test.cpp:6]: (warning) %d in format string (no. 1) requires a signed integer but the argument type is 'unsigned int'.\n", errout.str());
check("class foo {};\n"
"void foo(const int* cpi, foo f, bar b, bar* bp, double d, int i, bool bo) {\n"
@ -678,10 +678,10 @@ private:
" printf(\"%u\", bp);\n"
" printf(\"%u\", bo);\n" // bool shouldn't have a negative sign
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n"
"[test.cpp:4]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n"
"[test.cpp:5]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n"
"[test.cpp:6]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 1) requires an unsigned integer but the argument type is 'foo'.\n"
"[test.cpp:4]: (warning) %u in format string (no. 1) requires an unsigned integer but the argument type is 'const char *'.\n"
"[test.cpp:5]: (warning) %u in format string (no. 1) requires an unsigned integer but the argument type is 'double'.\n"
"[test.cpp:6]: (warning) %u in format string (no. 1) requires an unsigned integer but the argument type is 'int'.\n", errout.str());
check("class foo {};\n"
"void foo(const int* cpi, foo f, bar b, bar* bp, char c) {\n"
@ -691,8 +691,8 @@ private:
" printf(\"%p\", cpi);\n"
" printf(\"%p\", b);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) %p in format string (no. 1) requires an address given in the argument list.\n"
"[test.cpp:4]: (warning) %p in format string (no. 1) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (warning) %p in format string (no. 1) requires an address but the argument type is 'foo'.\n"
"[test.cpp:4]: (warning) %p in format string (no. 1) requires an address but the argument type is 'char'.\n", errout.str());
check("class foo {};\n"
"void foo(const int* cpi, foo f, bar b, bar* bp, double d) {\n"
@ -704,10 +704,10 @@ private:
" printf(\"%f\", b);\n"
" printf(\"%f\", (float)cpi);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) %e in format string (no. 1) requires a floating point number given in the argument list.\n"
"[test.cpp:4]: (warning) %E in format string (no. 1) requires a floating point number given in the argument list.\n"
"[test.cpp:5]: (warning) %f in format string (no. 1) requires a floating point number given in the argument list.\n"
"[test.cpp:6]: (warning) %G in format string (no. 1) requires a floating point number given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (warning) %e in format string (no. 1) requires a floating point number but the argument type is 'foo'.\n"
"[test.cpp:4]: (warning) %E in format string (no. 1) requires a floating point number but the argument type is 'const char *'.\n"
"[test.cpp:5]: (warning) %f in format string (no. 1) requires a floating point number but the argument type is 'int *'.\n"
"[test.cpp:6]: (warning) %G in format string (no. 1) requires a floating point number but the argument type is 'bar *'.\n", errout.str());
check("class foo;\n"
"void foo(foo f) {\n"
@ -715,9 +715,9 @@ private:
" printf(\"%f\", f);\n"
" printf(\"%p\", f);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n"
"[test.cpp:4]: (warning) %f in format string (no. 1) requires a floating point number given in the argument list.\n"
"[test.cpp:5]: (warning) %p in format string (no. 1) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 1) requires an unsigned integer but the argument type is 'foo'.\n"
"[test.cpp:4]: (warning) %f in format string (no. 1) requires a floating point number but the argument type is 'foo'.\n"
"[test.cpp:5]: (warning) %p in format string (no. 1) requires an address but the argument type is 'foo'.\n", errout.str());
// Ticket #4189 (Improve check (printf("%l") not detected)) tests (according to C99 7.19.6.1.7)
// False positive tests
@ -767,17 +767,38 @@ private:
" 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 long integer given in the argument list.\n"
"[test.cpp:5]: (warning) %lld in format string (no. 1) requires a signed long long integer given in the argument list.\n" , errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %hd in format string (no. 1) requires a signed integer but the argument type is 'unsigned int'.\n"
"[test.cpp:3]: (warning) %hhd in format string (no. 1) requires a signed integer but the argument type is 'unsigned int'.\n"
"[test.cpp:4]: (warning) %ld in format string (no. 1) requires a signed long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:5]: (warning) %lld in format string (no. 1) requires a signed long long integer but the argument type is 'unsigned int'.\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());
"}", false, false, Settings::Unix32);
ASSERT_EQUALS("[test.cpp:2]: (warning) %zd in format string (no. 1) requires a signed integer but the argument type is 'size_t {aka unsigned long}'.\n"
"[test.cpp:3]: (warning) %tu in format string (no. 1) requires an unsigned integer but the argument type is 'ptrdiff_t {aka long}'.\n", errout.str());
check("void foo(size_t s, ptrdiff_t p) {\n"
" printf(\"%zd\", s);\n"
" printf(\"%tu\", p);\n"
"}", false, false, Settings::Unix64);
ASSERT_EQUALS("[test.cpp:2]: (warning) %zd in format string (no. 1) requires a signed integer but the argument type is 'size_t {aka unsigned long}'.\n"
"[test.cpp:3]: (warning) %tu in format string (no. 1) requires an unsigned integer but the argument type is 'ptrdiff_t {aka long}'.\n", errout.str());
check("void foo(size_t s, ptrdiff_t p) {\n"
" printf(\"%zd\", s);\n"
" printf(\"%tu\", p);\n"
"}", false, false, Settings::Win32A);
ASSERT_EQUALS("[test.cpp:2]: (warning) %zd in format string (no. 1) requires a signed integer but the argument type is 'size_t {aka unsigned long}'.\n"
"[test.cpp:3]: (warning) %tu in format string (no. 1) requires an unsigned integer but the argument type is 'ptrdiff_t {aka long}'.\n", errout.str());
check("void foo(size_t s, ptrdiff_t p) {\n"
" printf(\"%zd\", s);\n"
" printf(\"%tu\", p);\n"
"}", false, false, Settings::Win64);
ASSERT_EQUALS("[test.cpp:2]: (warning) %zd in format string (no. 1) requires a signed integer but the argument type is 'size_t {aka unsigned long long}'.\n"
"[test.cpp:3]: (warning) %tu in format string (no. 1) requires an unsigned integer but the argument type is 'ptrdiff_t {aka long long}'.\n", errout.str());
check("void foo(unsigned int i) {\n"
" printf(\"%ld\", i);\n"
@ -787,12 +808,12 @@ private:
" 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());
ASSERT_EQUALS("[test.cpp:2]: (warning) %ld in format string (no. 1) requires a signed long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:3]: (warning) %lld in format string (no. 1) requires a signed long long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:4]: (warning) %lu in format string (no. 1) requires an unsigned long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:5]: (warning) %llu in format string (no. 1) requires an unsigned long long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:6]: (warning) %lx in format string (no. 1) requires a long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:7]: (warning) %llx in format string (no. 1) requires a long long integer but the argument type is 'unsigned int'.\n", errout.str());
check("class Foo {\n"
" double d;\n"
@ -810,155 +831,155 @@ private:
" foo->d, foo->bar[0].i, a[0],\n"
" f[0].d, f[0].baz.i, f[0].bar[0].i);\n"
"}");
ASSERT_EQUALS("[test.cpp:13]: (warning) %d in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:13]: (warning) %f in format string (no. 2) requires a floating point number given in the argument list.\n"
"[test.cpp:13]: (warning) %f in format string (no. 3) requires a floating point number given in the argument list.\n"
"[test.cpp:13]: (warning) %d in format string (no. 4) requires a signed integer given in the argument list.\n"
"[test.cpp:13]: (warning) %f in format string (no. 5) requires a floating point number given in the argument list.\n"
"[test.cpp:13]: (warning) %f in format string (no. 6) requires a floating point number given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:13]: (warning) %d in format string (no. 1) requires a signed integer but the argument type is 'double'.\n"
"[test.cpp:13]: (warning) %f in format string (no. 2) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:13]: (warning) %f in format string (no. 3) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:13]: (warning) %d in format string (no. 4) requires a signed integer but the argument type is 'double'.\n"
"[test.cpp:13]: (warning) %f in format string (no. 5) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:13]: (warning) %f in format string (no. 6) requires a floating point number but the argument type is 'int'.\n", errout.str());
check("short f() { return 0; }\n"
"void foo() { printf(\"%d %u %lu %I64u %I64d %f %lf %p\", f(), f(), f(), f(), f(), f(), f(), 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) %I64u in format string (no. 4) requires an unsigned long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 5) requires a signed long 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) %lf in format string (no. 7) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'short'.\n"
"[test.cpp:2]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'short'.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 4) requires an unsigned long long integer but the argument type is 'short'.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 5) requires a signed long long integer but the argument type is 'short'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 6) requires a floating point number but the argument type is 'short'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 7) requires a floating point number but the argument type is 'short'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'short'.\n", errout.str());
check("unsigned short f() { return 0; }\n"
"void foo() { printf(\"%u %d %ld %I64d %I64u %f %lf %p\", f(), 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) %I64d in format string (no. 4) requires a signed long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 5) requires an unsigned long 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) %lf in format string (no. 7) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer but the argument type is 'unsigned short'.\n"
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer but the argument type is 'unsigned short'.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 4) requires a signed long long integer but the argument type is 'unsigned short'.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 5) requires an unsigned long long integer but the argument type is 'unsigned short'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 6) requires a floating point number but the argument type is 'unsigned short'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 7) requires a floating point number but the argument type is 'unsigned short'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'unsigned short'.\n", errout.str());
check("int f() { return 0; }\n"
"void foo() { printf(\"%d %u %lu %I64u %I64d %f %lf %p\", f(), f(), f(), f(), f(), f(), f(), 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) %I64u in format string (no. 4) requires an unsigned long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 5) requires a signed long 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) %lf in format string (no. 7) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 4) requires an unsigned long long integer but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 5) requires a signed long long integer but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 6) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 7) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'int'.\n", errout.str());
check("unsigned int f() { return 0; }\n"
"void foo() { printf(\"%u %d %ld %I64d %I64u %f %lf %p\", f(), 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) %I64d in format string (no. 4) requires a signed long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 5) requires an unsigned long 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) %lf in format string (no. 7) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 4) requires a signed long long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 5) requires an unsigned long long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 6) requires a floating point number but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 7) requires a floating point number but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'unsigned int'.\n", errout.str());
check("long f() { return 0; }\n"
"void foo() { printf(\"%ld %u %lu %I64u %I64d %f %lf %p\", f(), f(), f(), f(), f(), f(), f(), 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) %I64u in format string (no. 4) requires an unsigned long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 5) requires a signed long 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) %lf in format string (no. 7) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'long'.\n"
"[test.cpp:2]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'long'.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 4) requires an unsigned long long integer but the argument type is 'long'.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 5) requires a signed long long integer but the argument type is 'long'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 6) requires a floating point number but the argument type is 'long'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 7) requires a floating point number but the argument type is 'long'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'long'.\n", errout.str());
check("unsigned long f() { return 0; }\n"
"void foo() { printf(\"%lu %d %ld %I64d %I64u %f %lf %p\", f(), 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) %I64d in format string (no. 4) requires a signed long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 5) requires an unsigned long 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) %lf in format string (no. 7) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer but the argument type is 'unsigned long'.\n"
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer but the argument type is 'unsigned long'.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 4) requires a signed long long integer but the argument type is 'unsigned long'.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 5) requires an unsigned long long integer but the argument type is 'unsigned long'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 6) requires a floating point number but the argument type is 'unsigned long'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 7) requires a floating point number but the argument type is 'unsigned long'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'unsigned long'.\n", errout.str());
check("long long f() { return 0; }\n"
"void foo() { printf(\"%lld %u %lu %I64u %I64d %f %lf %p\", f(), f(), f(), f(), f(), f(), f(), 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) %I64u in format string (no. 4) requires an unsigned long 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) %lf in format string (no. 7) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'long long'.\n"
"[test.cpp:2]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'long long'.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 4) requires an unsigned long long integer but the argument type is 'long long'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 6) requires a floating point number but the argument type is 'long long'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 7) requires a floating point number but the argument type is 'long long'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'long long'.\n", errout.str());
check("unsigned long long f() { return 0; }\n"
"void foo() { printf(\"%llu %d %ld %I64d %I64u %f %lf %p\", f(), 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) %I64d in format string (no. 4) requires a signed long 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) %lf in format string (no. 7) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer but the argument type is 'unsigned long long'.\n"
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer but the argument type is 'unsigned long long'.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 4) requires a signed long long integer but the argument type is 'unsigned long long'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 6) requires a floating point number but the argument type is 'unsigned long long'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 7) requires a floating point number but the argument type is 'unsigned long long'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'unsigned long long'.\n", errout.str());
check("float f() { return 0; }\n"
"void foo() { printf(\"%f %d %ld %u %lu %I64d %I64u %lf %p\", f(), f(), 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) %I64d in format string (no. 6) requires a signed long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 7) requires an unsigned long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 8) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 9) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer but the argument type is 'float'.\n"
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer but the argument type is 'float'.\n"
"[test.cpp:2]: (warning) %u in format string (no. 4) requires an unsigned integer but the argument type is 'float'.\n"
"[test.cpp:2]: (warning) %lu in format string (no. 5) requires an unsigned long integer but the argument type is 'float'.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 6) requires a signed long long integer but the argument type is 'float'.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 7) requires an unsigned long long integer but the argument type is 'float'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 8) requires a floating point number but the argument type is 'float'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 9) requires an address but the argument type is 'float'.\n", errout.str());
check("double f() { return 0; }\n"
"void foo() { printf(\"%f %d %ld %u %lu %I64d %I64u %lf %p\", f(), f(), 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) %I64d in format string (no. 6) requires a signed long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 7) requires an unsigned long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 8) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 9) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer but the argument type is 'double'.\n"
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer but the argument type is 'double'.\n"
"[test.cpp:2]: (warning) %u in format string (no. 4) requires an unsigned integer but the argument type is 'double'.\n"
"[test.cpp:2]: (warning) %lu in format string (no. 5) requires an unsigned long integer but the argument type is 'double'.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 6) requires a signed long long integer but the argument type is 'double'.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 7) requires an unsigned long long integer but the argument type is 'double'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 8) requires a floating point number but the argument type is 'double'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 9) requires an address but the argument type is 'double'.\n", errout.str());
check("long double f() { return 0; }\n"
"void foo() { printf(\"%lf %d %ld %u %lu %I64d %I64u %f %p\", f(), f(), 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) %I64d in format string (no. 6) requires a signed long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 7) requires an unsigned long long integer given in the argument list.\n"
"[test.cpp:2]: (warning) %f in format string (no. 8) requires a floating point number given in the argument list.\n"
"[test.cpp:2]: (warning) %p in format string (no. 9) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer but the argument type is 'long double'.\n"
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer but the argument type is 'long double'.\n"
"[test.cpp:2]: (warning) %u in format string (no. 4) requires an unsigned integer but the argument type is 'long double'.\n"
"[test.cpp:2]: (warning) %lu in format string (no. 5) requires an unsigned long integer but the argument type is 'long double'.\n"
"[test.cpp:2]: (warning) %I64d in format string (no. 6) requires a signed long long integer but the argument type is 'long double'.\n"
"[test.cpp:2]: (warning) %I64u in format string (no. 7) requires an unsigned long long integer but the argument type is 'long double'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 8) requires a floating point number but the argument type is 'long double'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 9) requires an address but the argument type is 'long double'.\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) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address but the argument type is 'int'.\n", errout.str());
check("struct Fred { int i; } f;\n"
"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) %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) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address but the argument type is 'int'.\n", errout.str());
check("struct Fred { unsigned int u; } f;\n"
"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. 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) %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) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address but the argument type is 'unsigned int'.\n", errout.str());
check("struct Fred { unsigned int ui() { return 0; } } f;\n"
"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. 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) %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) %p in format string (no. 6) requires an address given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires a signed integer but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %ld in format string (no. 3) requires a signed long integer but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %lf in format string (no. 5) requires a floating point number but the argument type is 'unsigned int'.\n"
"[test.cpp:2]: (warning) %p in format string (no. 6) requires an address but the argument type is 'unsigned int'.\n", errout.str());
// #4975
check("void f(int len, int newline) {\n"
@ -970,56 +991,56 @@ private:
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());
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'int'.\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());
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'int'.\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());
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'int'.\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());
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'int'.\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());
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'int'.\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());
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lu in format string (no. 3) requires an unsigned long integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %f in format string (no. 4) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %lf in format string (no. 5) requires a floating point number but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'int'.\n", errout.str());
check("struct Fred { int32_t i; } f;\n"
"struct Fred & bar() { };\n"
@ -1037,21 +1058,21 @@ private:
"void f() {\n"
" printf(\"%f\", foo()[0]);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (warning) %f in format string (no. 1) requires a floating point number given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (warning) %f in format string (no. 1) requires a floating point number but the argument type is 'int *'.\n", errout.str());
check("struct Base { int length() { } };\n"
"struct Derived : public Base { };\n"
"void foo(Derived * d) {\n"
" printf(\"%f\", d.length());\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (warning) %f in format string (no. 1) requires a floating point number given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (warning) %f in format string (no. 1) requires a floating point number but the argument type is 'int'.\n", errout.str());
check("std::vector<int> v;\n"
"void foo() {\n"
" printf(\"%d %u %f\", v[0], v[0], v[0]);\n"
"}\n");
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) %f in format string (no. 3) requires a floating point number given in the argument list.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires an unsigned integer but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %f in format string (no. 3) requires a floating point number but the argument type is 'int'.\n", errout.str());
}
@ -1093,13 +1114,34 @@ private:
" printf(\"%I32d %I32u %I32x\", u32, u32, u32);\n"
" printf(\"%I64d %I64u %I64x\", i64, i64, i64);\n"
" printf(\"%I64d %I64u %I64x\", u64, u64, u64);\n"
"}");
ASSERT_EQUALS("[test.cpp:8]: (warning) %Id in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:9]: (warning) %Iu in format string (no. 2) requires an unsigned integer given in the argument list.\n"
"[test.cpp:10]: (warning) %I32u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
"[test.cpp:11]: (warning) %I32d in format string (no. 1) requires a signed integer given in the argument list.\n"
"[test.cpp:12]: (warning) %I64u in format string (no. 2) requires an unsigned long long integer given in the argument list.\n"
"[test.cpp:13]: (warning) %I64d in format string (no. 1) requires a signed long long integer given in the argument list.\n", errout.str());
"}", false, false, Settings::Win32A);
ASSERT_EQUALS("[test.cpp:8]: (warning) %Id in format string (no. 1) requires a signed integer but the argument type is 'size_t {aka unsigned long}'.\n"
"[test.cpp:9]: (warning) %Iu in format string (no. 2) requires an unsigned integer but the argument type is 'ptrdiff_t {aka long}'.\n"
"[test.cpp:10]: (warning) %I32u in format string (no. 2) requires an unsigned integer but the argument type is '__int32 {aka int}'.\n"
"[test.cpp:11]: (warning) %I32d in format string (no. 1) requires a signed integer but the argument type is 'unsigned __int32 {aka unsigned int}'.\n"
"[test.cpp:12]: (warning) %I64u in format string (no. 2) requires an unsigned long long integer but the argument type is '__int64 {aka long long}'.\n"
"[test.cpp:13]: (warning) %I64d in format string (no. 1) requires a signed long long integer but the argument type is 'unsigned __int64 {aka unsigned long long}'.\n", errout.str());
check("void foo() {\n"
" size_t s;\n"
" ptrdiff_t p;\n"
" __int32 i32;\n"
" unsigned __int32 u32;\n"
" __int64 i64;\n"
" unsigned __int64 u64;\n"
" printf(\"%Id %Iu %Ix\", s, s, s);\n"
" printf(\"%Id %Iu %Ix\", p, p, p);\n"
" printf(\"%I32d %I32u %I32x\", i32, i32, i32);\n"
" printf(\"%I32d %I32u %I32x\", u32, u32, u32);\n"
" printf(\"%I64d %I64u %I64x\", i64, i64, i64);\n"
" printf(\"%I64d %I64u %I64x\", u64, u64, u64);\n"
"}", false, false, Settings::Win64);
ASSERT_EQUALS("[test.cpp:8]: (warning) %Id in format string (no. 1) requires a signed integer but the argument type is 'size_t {aka unsigned long long}'.\n"
"[test.cpp:9]: (warning) %Iu in format string (no. 2) requires an unsigned integer but the argument type is 'ptrdiff_t {aka long long}'.\n"
"[test.cpp:10]: (warning) %I32u in format string (no. 2) requires an unsigned integer but the argument type is '__int32 {aka int}'.\n"
"[test.cpp:11]: (warning) %I32d in format string (no. 1) requires a signed integer but the argument type is 'unsigned __int32 {aka unsigned int}'.\n"
"[test.cpp:12]: (warning) %I64u in format string (no. 2) requires an unsigned long long integer but the argument type is '__int64 {aka long long}'.\n"
"[test.cpp:13]: (warning) %I64d in format string (no. 1) requires a signed long long integer but the argument type is 'unsigned __int64 {aka unsigned long long}'.\n", errout.str());
check("void foo() {\n"
" size_t s;\n"

View File

@ -8208,11 +8208,11 @@ private:
"unsigned int sizeof_wchar_t ; sizeof_wchar_t = 4 ; "
"unsigned int sizeof_pointer ; sizeof_pointer = 8 ; "
"unsigned int sizeof_size_t ; sizeof_size_t = 8 ; "
"unsigned long long a ; "
"long long b ; "
"long long c ; "
"long long d ; "
"unsigned long long e ;";
"unsigned long a ; "
"long b ; "
"long c ; "
"long d ; "
"unsigned long e ;";
ASSERT_EQUALS(expected, tokenizeAndStringify(code, true, true, Settings::Unix64));
}