From 5c4c3973727b133f2df33a099187d3af5a73cc9d Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Sun, 22 Sep 2013 06:56:31 +0200 Subject: [PATCH] CheckIO: add scanf argument type checking. Floating point and integer checking is complete but string checking is incomplete and character checking is missing. Ticket #4099 --- lib/checkio.cpp | 394 ++++++++++++++++++++++-- lib/checkio.h | 13 +- lib/tokenize.cpp | 4 +- test/testio.cpp | 767 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 1145 insertions(+), 33 deletions(-) diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 3a24c7e00..08defc59a 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -537,14 +537,294 @@ void CheckIO::checkWrongPrintfScanfArguments() if (argInfo.typeToken) { if (scan) { - if (warning && ((!argInfo.variableInfo->isPointer() && !argInfo.variableInfo->isArray()) || argInfo.typeToken->strAt(-1) == "const")) - invalidScanfArgTypeError(tok, tok->str(), numFormat); - - if (*i == 's' && argInfo.variableInfo && argInfo.isKnownType() && argInfo.variableInfo->isArray() && (argInfo.variableInfo->dimensions().size() == 1) && argInfo.variableInfo->dimensions()[0].known) { - if (!width.empty()) { - int numWidth = std::atoi(width.c_str()); - if (numWidth != (argInfo.variableInfo->dimension(0) - 1)) - invalidScanfFormatWidthError(tok, numFormat, numWidth, argInfo.variableInfo); + std::string specifier; + bool done = false; + while (!done) { + switch (*i) { + case 's': + specifier += *i; + if (argInfo.variableInfo && argInfo.isKnownType() && argInfo.variableInfo->isArray() && (argInfo.variableInfo->dimensions().size() == 1) && argInfo.variableInfo->dimensions()[0].known) { + if (!width.empty()) { + int numWidth = std::atoi(width.c_str()); + if (numWidth != (argInfo.variableInfo->dimension(0) - 1)) + invalidScanfFormatWidthError(tok, numFormat, numWidth, argInfo.variableInfo); + } + } + if (argListTok->type() != Token::eString && + argInfo.isKnownType() && argInfo.isArrayOrPointer() && + (!Token::Match(argInfo.typeToken, "char|wchar_t") || + argInfo.typeToken->strAt(-1) == "const")) { + invalidScanfArgTypeError_s(tok, numFormat, specifier, &argInfo); + } + done = true; + break; + case 'x': + case 'X': + case 'o': + specifier += *i; + if (argInfo.typeToken->type() == Token::eString) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + else if (argInfo.isKnownType()) { + if (!argInfo.isArrayOrPointer() || argInfo.typeToken->strAt(-1) == "const") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + else { + switch (specifier[0]) { + case 'h': + if (specifier[1] == 'h') { + if (argInfo.typeToken->str() != "char") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + } else if (argInfo.typeToken->str() != "short") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 'l': + if (specifier[1] == 'l') { + if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + else if (argInfo.typeToken->originalName() == "size_t" || + argInfo.typeToken->originalName() == "ptrdiff_t" || + argInfo.typeToken->originalName() == "intmax_t" || + argInfo.typeToken->originalName() == "uintmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + } else if (argInfo.typeToken->str() != "long" || argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + else if (argInfo.typeToken->originalName() == "size_t" || + argInfo.typeToken->originalName() == "ptrdiff_t" || + argInfo.typeToken->originalName() == "intmax_t" || + argInfo.typeToken->originalName() == "uintmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 'I': + if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 'j': + if (argInfo.typeToken->originalName() != "uintmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 'z': + if (argInfo.typeToken->originalName() != "size_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 't': + if (argInfo.typeToken->originalName() != "ptrdiff_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 'L': + if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + default: + if (argInfo.typeToken->str() != "int") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + else if (argInfo.typeToken->originalName() == "size_t" || + argInfo.typeToken->originalName() == "ptrdiff_t" || + argInfo.typeToken->originalName() == "intmax_t" || + argInfo.typeToken->originalName() == "uintmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + } + } + } + done = true; + break; + case 'n': + case 'd': + case 'i': + specifier += *i; + if (argInfo.typeToken->type() == Token::eString) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + else if (argInfo.isKnownType()) { + if (argInfo.typeToken->isUnsigned() || !argInfo.isArrayOrPointer() || argInfo.typeToken->strAt(-1) == "const") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + else { + switch (specifier[0]) { + case 'h': + if (specifier[1] == 'h') { + if (argInfo.typeToken->str() != "char") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + } else if (argInfo.typeToken->str() != "short") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + break; + case 'l': + if (specifier[1] == 'l') { + if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + else if (argInfo.typeToken->originalName() == "ptrdiff_t" || + argInfo.typeToken->originalName() == "intmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + } else if (argInfo.typeToken->str() != "long" || argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + else if (argInfo.typeToken->originalName() == "ptrdiff_t" || + argInfo.typeToken->originalName() == "intmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + break; + case 'I': + if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + break; + case 'j': + if (argInfo.typeToken->originalName() != "intmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + break; + case 'z': + if (argInfo.typeToken->originalName() != "size_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + break; + case 't': + if (argInfo.typeToken->originalName() != "ptrdiff_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + break; + case 'L': + if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + break; + default: + if (argInfo.typeToken->str() != "int") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + else if (argInfo.typeToken->originalName() == "ptrdiff_t" || + argInfo.typeToken->originalName() == "intmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, false); + break; + } + } + } + done = true; + break; + case 'u': + specifier += *i; + if (argInfo.typeToken->type() == Token::eString) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + else if (argInfo.isKnownType()) { + if (!argInfo.typeToken->isUnsigned() || !argInfo.isArrayOrPointer() || argInfo.typeToken->strAt(-1) == "const") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + else { + switch (specifier[0]) { + case 'h': + if (specifier[1] == 'h') { + if (argInfo.typeToken->str() != "char") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + } else if (argInfo.typeToken->str() != "short") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 'l': + if (specifier[1] == 'l') { + if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + else if (argInfo.typeToken->originalName() == "size_t" || + argInfo.typeToken->originalName() == "uintmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + } else if (argInfo.typeToken->str() != "long" || argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + else if (argInfo.typeToken->originalName() == "size_t" || + argInfo.typeToken->originalName() == "uintmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 'I': + if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 'j': + if (argInfo.typeToken->originalName() != "uintmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 'z': + if (argInfo.typeToken->originalName() != "size_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 't': + if (argInfo.typeToken->originalName() != "ptrdiff_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + case 'L': + if (argInfo.typeToken->str() != "long" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + default: + if (argInfo.typeToken->str() != "int") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + else if (argInfo.typeToken->originalName() == "size_t" || + argInfo.typeToken->originalName() == "uintmax_t") + invalidScanfArgTypeError_int(tok, numFormat, specifier, &argInfo, true); + break; + } + } + } + done = true; + break; + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + case 'a': + specifier += *i; + if (argInfo.typeToken->type() == Token::eString) + invalidScanfArgTypeError_float(tok, numFormat, specifier, &argInfo); + else if (argInfo.isKnownType()) { + if (!argInfo.isArrayOrPointer() || argInfo.typeToken->strAt(-1) == "const") + invalidScanfArgTypeError_float(tok, numFormat, specifier, &argInfo); + else { + switch (specifier[0]) { + case 'l': + if (specifier[1] == 'l') { + if (argInfo.typeToken->str() != "double" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_float(tok, numFormat, specifier, &argInfo); + } else if (argInfo.typeToken->str() != "double" || argInfo.typeToken->isLong()) + invalidScanfArgTypeError_float(tok, numFormat, specifier, &argInfo); + break; + case 'L': + if (argInfo.typeToken->str() != "double" || !argInfo.typeToken->isLong()) + invalidScanfArgTypeError_float(tok, numFormat, specifier, &argInfo); + break; + default: + if (argInfo.typeToken->str() != "float") + invalidScanfArgTypeError_float(tok, numFormat, specifier, &argInfo); + break; + } + } + } + done = true; + break; + case 'I': + if (i+1 != formatString.end() && *(i+1) == '6' && + i+2 != formatString.end() && *(i+2) == '4') { + specifier += *i++; + specifier += *i++; + if ((i+1) != formatString.end() && !isalpha(*(i+1))) { + specifier += *i; + invalidLengthModifierError(tok, numFormat, specifier); + done = true; + } else { + specifier += *i++; + } + } else { + specifier += *i; + invalidLengthModifierError(tok, numFormat, specifier); + done = true; + } + break; + case 'h': + case 'l': + if (i+1 != formatString.end() && *(i+1) == *i) + specifier += *i++; + // fallthrough + case 'j': + case 'q': + case 't': + case 'z': + case 'L': + // Expect an alphabetical character after these specifiers + if (i != formatString.end() && !isalpha(*(i+1))) { + specifier += *i; + invalidLengthModifierError(tok, numFormat, specifier); + done = true; + } else { + specifier += *i++; + } + break; + default: + done = true; + break; } } } else if (!scan && warning) { @@ -560,7 +840,7 @@ void CheckIO::checkWrongPrintfScanfArguments() break; case 'n': if ((argInfo.variableInfo && argInfo.isKnownType() && (!argInfo.isArrayOrPointer() || argInfo.typeToken->strAt(-1) == "const")) || argListTok->type() == Token::eString) - invalidPrintfArgTypeError_n(tok, numFormat); + invalidPrintfArgTypeError_n(tok, numFormat, &argInfo); done = true; break; case 'c': @@ -762,13 +1042,18 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * tok, const Settings *settings) , functionInfo(0) , element(false) , _template(false) + , address(false) , tempToken(0) { if (tok) { if (tok->type() == Token::eString) { typeToken = tok; return; - } else if (tok->type() == Token::eVariable || tok->type() == Token::eFunction || Token::Match(tok, "%type% ::")) { + } else if (tok->str() == "&" || tok->type() == Token::eVariable || tok->type() == Token::eFunction || Token::Match(tok, "%type% ::")) { + if (tok->str() == "&") { + address = true; + tok = tok->next(); + } while (Token::Match(tok, "%type% ::")) tok = tok->tokAt(2); if (!tok || !(tok->type() == Token::eVariable || tok->type() == Token::eFunction)) @@ -783,6 +1068,8 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * tok, const Settings *settings) const Function * function = varTok->link()->previous()->function(); if (function && function->retDef) { typeToken = function->retDef; + if (typeToken->str() == "const") + typeToken = typeToken->next(); functionInfo = function; element = true; return; @@ -793,6 +1080,8 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * tok, const Settings *settings) const Function * function = tok1->linkAt(-1)->previous()->function(); if (function && function->retDef) { typeToken = function->retDef; + if (typeToken->str() == "const") + typeToken = typeToken->next(); functionInfo = function; element = false; return; @@ -925,7 +1214,9 @@ bool CheckIO::ArgumentInfo::isStdContainer(const Token *tok) bool CheckIO::ArgumentInfo::isArrayOrPointer() const { - if (variableInfo && !_template) { + if (address) + return true; + else if (variableInfo && !_template) { return variableInfo->isArrayOrPointer(); } else { const Token *tok = typeToken; @@ -1001,22 +1292,82 @@ void CheckIO::wrongPrintfScanfPosixParameterPositionError(const Token* tok, cons reportError(tok, Severity::warning, "wrongPrintfScanfParameterPositionError", errmsg.str()); } -void CheckIO::invalidScanfArgTypeError(const Token* tok, const std::string &functionName, unsigned int numFormat) +void CheckIO::invalidScanfArgTypeError_s(const Token* tok, unsigned int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) { std::ostringstream errmsg; - errmsg << functionName << " argument no. " << numFormat << ": requires a non-const pointer or array as argument."; - reportError(tok, Severity::warning, "invalidScanfArgType", errmsg.str()); + errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires a \'"; + if (specifier[0] == 's') + errmsg << "char"; + else if (specifier[0] == 'S') + errmsg << "wchar_t"; + errmsg << " *\' but the argument type is "; + argumentType(errmsg, argInfo); + errmsg << "."; + reportError(tok, Severity::warning, "invalidScanfArgType_s", errmsg.str()); } +void CheckIO::invalidScanfArgTypeError_int(const Token* tok, unsigned int numFormat, const std::string& specifier, const ArgumentInfo* argInfo, bool isUnsigned) +{ + std::ostringstream errmsg; + errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires \'"; + if (specifier[0] == 'h') { + if (specifier[1] == 'h') + errmsg << (isUnsigned ? "unsigned " : "") << "char"; + else + errmsg << (isUnsigned ? "unsigned " : "") << "short"; + } else if (specifier[0] == 'l') { + if (specifier[1] == 'l') + errmsg << (isUnsigned ? "unsigned " : "") << "long long"; + else + errmsg << (isUnsigned ? "unsigned " : "") << "long"; + } else if (specifier[0] == 'I') { + errmsg << (isUnsigned ? "unsigned " : "") << "__int64"; + } else if (specifier[0] == 'j') { + if (isUnsigned) + errmsg << "uintmax_t"; + else + errmsg << "intmax_t"; + } else if (specifier[0] == 'z') { + errmsg << "size_t"; + } else if (specifier[0] == 't') { + errmsg << (isUnsigned ? "unsigned " : "") << "ptrdiff_t"; + } else if (specifier[0] == 'L') { + errmsg << (isUnsigned ? "unsigned " : "") << "long long"; + } else { + errmsg << (isUnsigned ? "unsigned " : "") << "int"; + } + errmsg << " *\' but the argument type is "; + argumentType(errmsg, argInfo); + errmsg << "."; + reportError(tok, Severity::warning, "invalidScanfArgType_int", errmsg.str()); +} +void CheckIO::invalidScanfArgTypeError_float(const Token* tok, unsigned int numFormat, const std::string& specifier, const ArgumentInfo* argInfo) +{ + std::ostringstream errmsg; + errmsg << "%" << specifier << " in format string (no. " << numFormat << ") requires \'"; + if (specifier[0] == 'l' && specifier[1] != 'l') + errmsg << "double"; + else if (specifier[0] == 'L') + errmsg << "long double"; + else + errmsg << "float"; + errmsg << " *\' but the argument type is "; + argumentType(errmsg, argInfo); + errmsg << "."; + reportError(tok, Severity::warning, "invalidScanfArgType_float", errmsg.str()); +} + void CheckIO::invalidPrintfArgTypeError_s(const Token* tok, unsigned int numFormat) { std::ostringstream errmsg; errmsg << "%s in format string (no. " << numFormat << ") requires a char* given in the argument list."; reportError(tok, Severity::warning, "invalidPrintfArgType_s", errmsg.str()); } -void CheckIO::invalidPrintfArgTypeError_n(const Token* tok, unsigned int numFormat) +void CheckIO::invalidPrintfArgTypeError_n(const Token* tok, unsigned int numFormat, const ArgumentInfo* argInfo) { std::ostringstream errmsg; - errmsg << "%n in format string (no. " << numFormat << ") requires a pointer to an non-const integer given in the argument list."; + errmsg << "%n in format string (no. " << numFormat << ") requires \'int *\' but the argument type is "; + argumentType(errmsg, argInfo); + errmsg << "."; reportError(tok, Severity::warning, "invalidPrintfArgType_n", errmsg.str()); } void CheckIO::invalidPrintfArgTypeError_p(const Token* tok, unsigned int numFormat, const ArgumentInfo* argInfo) @@ -1093,6 +1444,8 @@ void CheckIO::argumentType(std::ostream& os, const ArgumentInfo * argInfo) os << "const char *"; } else { if (type->originalName().empty()) { + if (type->strAt(-1) == "const") + os << "const "; while (Token::Match(type, "const|struct")) { os << type->str() << " "; type = type->next(); @@ -1102,12 +1455,17 @@ void CheckIO::argumentType(std::ostream& os, const ArgumentInfo * argInfo) os << " *"; else if (argInfo->variableInfo && !argInfo->element && argInfo->variableInfo->isArray()) os << " *"; + if (argInfo->address) + os << " *"; } else { if ((type->originalName() == "__int64" || type->originalName() == "__int32") && type->isUnsigned()) os << "unsigned "; - os << type->originalName() << " {aka "; + os << type->originalName(); + if (type->strAt(1) == "*" || argInfo->address) + os << " *"; + os << " {aka "; type->stringify(os, false, true); - if (type->strAt(1) == "*") + if (type->strAt(1) == "*" || argInfo->address) os << " *"; os << "}"; } diff --git a/lib/checkio.h b/lib/checkio.h index b24d09287..fde9541a7 100644 --- a/lib/checkio.h +++ b/lib/checkio.h @@ -86,6 +86,7 @@ private: const Function *functionInfo; bool element; bool _template; + bool address; Token *tempToken; private: @@ -107,9 +108,11 @@ private: unsigned int numFunction); void wrongPrintfScanfPosixParameterPositionError(const Token* tok, const std::string& functionName, unsigned int index, unsigned int numFunction); - void invalidScanfArgTypeError(const Token* tok, const std::string &functionName, unsigned int numFormat); + void invalidScanfArgTypeError_s(const Token* tok, unsigned int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); + void invalidScanfArgTypeError_int(const Token* tok, unsigned int numFormat, const std::string& specifier, const ArgumentInfo* argInfo, bool isUnsigned); + void invalidScanfArgTypeError_float(const Token* tok, unsigned int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); void invalidPrintfArgTypeError_s(const Token* tok, unsigned int numFormat); - void invalidPrintfArgTypeError_n(const Token* tok, unsigned int numFormat); + void invalidPrintfArgTypeError_n(const Token* tok, unsigned int numFormat, const ArgumentInfo* argInfo); void invalidPrintfArgTypeError_p(const Token* tok, unsigned int numFormat, const ArgumentInfo* argInfo); void invalidPrintfArgTypeError_int(const Token* tok, unsigned int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); void invalidPrintfArgTypeError_uint(const Token* tok, unsigned int numFormat, const std::string& specifier, const ArgumentInfo* argInfo); @@ -130,9 +133,11 @@ private: c.useClosedFileError(0); c.invalidScanfError(0, false); c.wrongPrintfScanfArgumentsError(0,"printf",3,2); - c.invalidScanfArgTypeError(0, "scanf", 1); + c.invalidScanfArgTypeError_s(0, 1, "s", NULL); + c.invalidScanfArgTypeError_int(0, 1, "d", NULL, false); + c.invalidScanfArgTypeError_float(0, 1, "f", NULL); c.invalidPrintfArgTypeError_s(0, 1); - c.invalidPrintfArgTypeError_n(0, 1); + c.invalidPrintfArgTypeError_n(0, 1, NULL); c.invalidPrintfArgTypeError_p(0, 1, NULL); c.invalidPrintfArgTypeError_int(0, 1, "X", NULL); c.invalidPrintfArgTypeError_uint(0, 1, "u", NULL); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index c6abc9807..dc3704cf1 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5364,7 +5364,7 @@ void Tokenizer::simplifyPlatformTypes() tok->deleteThis(); } - if (Token::Match(tok, "size_t|uintptr_t")) { + if (Token::Match(tok, "size_t|uintptr_t|uintmax_t")) { if (inStd) tok->originalName("std::" + tok->str()); else @@ -5383,7 +5383,7 @@ void Tokenizer::simplifyPlatformTypes() tok->str("int"); break; } - } else if (Token::Match(tok, "ssize_t|ptrdiff_t|intptr_t")) { + } else if (Token::Match(tok, "ssize_t|ptrdiff_t|intptr_t|intmax_t")) { if (inStd) tok->originalName("std::" + tok->str()); else diff --git a/test/testio.cpp b/test/testio.cpp index 241adfd1a..78aede7cf 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -552,6 +552,755 @@ private: " sscanf(input, \"%5s\", output);\n" "}", true); ASSERT_EQUALS("", errout.str()); + + check("const unsigned int * foo() { }\n" + "void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, \"str\", L\"str\", foo(), &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:23]: (warning) %u in format string (no. 1) requires 'unsigned int *' but the argument type is 'bool *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 2) requires 'unsigned int *' but the argument type is 'char *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed char *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 4) requires 'unsigned int *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 5) requires 'unsigned int *' but the argument type is 'short *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 6) requires 'unsigned int *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 7) requires 'unsigned int *' but the argument type is 'int *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 9) requires 'unsigned int *' but the argument type is 'long *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 10) requires 'unsigned int *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 11) requires 'unsigned int *' but the argument type is 'long long *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 12) requires 'unsigned int *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 13) requires 'unsigned int *' but the argument type is 'float *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 14) requires 'unsigned int *' but the argument type is 'double *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 15) requires 'unsigned int *' but the argument type is 'long double *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 16) requires 'unsigned int *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 17) requires 'unsigned int *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 18) requires 'unsigned int *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 19) requires 'unsigned int *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 20) requires 'unsigned int *' but the argument type is 'void * *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 21) requires 'unsigned int *' but the argument type is 'void *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 22) requires 'unsigned int *' but the argument type is 'const char *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 23) requires 'unsigned int *' but the argument type is 'const wchar_t *'.\n" + "[test.cpp:23]: (warning) %u in format string (no. 24) requires 'unsigned int *' but the argument type is 'const unsigned int *'.\n", errout.str()); + + check("void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:22]: (warning) %lu in format string (no. 1) requires 'unsigned long *' but the argument type is 'bool *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 2) requires 'unsigned long *' but the argument type is 'char *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 3) requires 'unsigned long *' but the argument type is 'signed char *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 4) requires 'unsigned long *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 5) requires 'unsigned long *' but the argument type is 'short *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 6) requires 'unsigned long *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 7) requires 'unsigned long *' but the argument type is 'int *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 8) requires 'unsigned long *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 9) requires 'unsigned long *' but the argument type is 'long *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 11) requires 'unsigned long *' but the argument type is 'long long *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 12) requires 'unsigned long *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 13) requires 'unsigned long *' but the argument type is 'float *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 14) requires 'unsigned long *' but the argument type is 'double *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 15) requires 'unsigned long *' but the argument type is 'long double *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 16) requires 'unsigned long *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 17) requires 'unsigned long *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 18) requires 'unsigned long *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 19) requires 'unsigned long *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 20) requires 'unsigned long *' but the argument type is 'void * *'.\n" + "[test.cpp:22]: (warning) %lu in format string (no. 21) requires 'unsigned long *' but the argument type is 'void *'.\n", errout.str()); + + check("void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:22]: (warning) %llu in format string (no. 1) requires 'unsigned long long *' but the argument type is 'bool *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 2) requires 'unsigned long long *' but the argument type is 'char *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 3) requires 'unsigned long long *' but the argument type is 'signed char *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 4) requires 'unsigned long long *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 5) requires 'unsigned long long *' but the argument type is 'short *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 6) requires 'unsigned long long *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 7) requires 'unsigned long long *' but the argument type is 'int *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 8) requires 'unsigned long long *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 9) requires 'unsigned long long *' but the argument type is 'long *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 10) requires 'unsigned long long *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 11) requires 'unsigned long long *' but the argument type is 'long long *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 13) requires 'unsigned long long *' but the argument type is 'float *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 14) requires 'unsigned long long *' but the argument type is 'double *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 15) requires 'unsigned long long *' but the argument type is 'long double *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 16) requires 'unsigned long long *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 17) requires 'unsigned long long *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 18) requires 'unsigned long long *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 19) requires 'unsigned long long *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 20) requires 'unsigned long long *' but the argument type is 'void * *'.\n" + "[test.cpp:22]: (warning) %llu in format string (no. 21) requires 'unsigned long long *' but the argument type is 'void *'.\n", errout.str()); + + check("void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu %hu\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:22]: (warning) %hu in format string (no. 1) requires 'unsigned short *' but the argument type is 'bool *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 2) requires 'unsigned short *' but the argument type is 'char *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 3) requires 'unsigned short *' but the argument type is 'signed char *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 4) requires 'unsigned short *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 5) requires 'unsigned short *' but the argument type is 'short *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 7) requires 'unsigned short *' but the argument type is 'int *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 8) requires 'unsigned short *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 9) requires 'unsigned short *' but the argument type is 'long *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 10) requires 'unsigned short *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 11) requires 'unsigned short *' but the argument type is 'long long *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 12) requires 'unsigned short *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 13) requires 'unsigned short *' but the argument type is 'float *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 14) requires 'unsigned short *' but the argument type is 'double *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 15) requires 'unsigned short *' but the argument type is 'long double *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 16) requires 'unsigned short *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 17) requires 'unsigned short *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 18) requires 'unsigned short *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 19) requires 'unsigned short *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 20) requires 'unsigned short *' but the argument type is 'void * *'.\n" + "[test.cpp:22]: (warning) %hu in format string (no. 21) requires 'unsigned short *' but the argument type is 'void *'.\n", errout.str()); + + check("void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:22]: (warning) %hhu in format string (no. 1) requires 'unsigned char *' but the argument type is 'bool *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 2) requires 'unsigned char *' but the argument type is 'char *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 3) requires 'unsigned char *' but the argument type is 'signed char *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 5) requires 'unsigned char *' but the argument type is 'short *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 6) requires 'unsigned char *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 7) requires 'unsigned char *' but the argument type is 'int *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 8) requires 'unsigned char *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 9) requires 'unsigned char *' but the argument type is 'long *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 10) requires 'unsigned char *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 11) requires 'unsigned char *' but the argument type is 'long long *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 12) requires 'unsigned char *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 13) requires 'unsigned char *' but the argument type is 'float *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 14) requires 'unsigned char *' but the argument type is 'double *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 15) requires 'unsigned char *' but the argument type is 'long double *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 16) requires 'unsigned char *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 17) requires 'unsigned char *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 18) requires 'unsigned char *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 19) requires 'unsigned char *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 20) requires 'unsigned char *' but the argument type is 'void * *'.\n" + "[test.cpp:22]: (warning) %hhu in format string (no. 21) requires 'unsigned char *' but the argument type is 'void *'.\n", errout.str()); + + check("void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:22]: (warning) %Lu in format string (no. 1) requires 'unsigned long long *' but the argument type is 'bool *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 2) requires 'unsigned long long *' but the argument type is 'char *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 3) requires 'unsigned long long *' but the argument type is 'signed char *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 4) requires 'unsigned long long *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 5) requires 'unsigned long long *' but the argument type is 'short *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 6) requires 'unsigned long long *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 7) requires 'unsigned long long *' but the argument type is 'int *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 8) requires 'unsigned long long *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 9) requires 'unsigned long long *' but the argument type is 'long *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 10) requires 'unsigned long long *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 11) requires 'unsigned long long *' but the argument type is 'long long *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 13) requires 'unsigned long long *' but the argument type is 'float *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 14) requires 'unsigned long long *' but the argument type is 'double *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 15) requires 'unsigned long long *' but the argument type is 'long double *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 16) requires 'unsigned long long *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 17) requires 'unsigned long long *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 18) requires 'unsigned long long *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 19) requires 'unsigned long long *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 20) requires 'unsigned long long *' but the argument type is 'void * *'.\n" + "[test.cpp:22]: (warning) %Lu in format string (no. 21) requires 'unsigned long long *' but the argument type is 'void *'.\n", errout.str()); + + check("void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju %ju\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:22]: (warning) %ju in format string (no. 1) requires 'uintmax_t *' but the argument type is 'bool *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 2) requires 'uintmax_t *' but the argument type is 'char *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 3) requires 'uintmax_t *' but the argument type is 'signed char *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 4) requires 'uintmax_t *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 5) requires 'uintmax_t *' but the argument type is 'short *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 6) requires 'uintmax_t *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 7) requires 'uintmax_t *' but the argument type is 'int *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 8) requires 'uintmax_t *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 9) requires 'uintmax_t *' but the argument type is 'long *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 10) requires 'uintmax_t *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 11) requires 'uintmax_t *' but the argument type is 'long long *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 12) requires 'uintmax_t *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 13) requires 'uintmax_t *' but the argument type is 'float *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 14) requires 'uintmax_t *' but the argument type is 'double *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 15) requires 'uintmax_t *' but the argument type is 'long double *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 16) requires 'uintmax_t *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 17) requires 'uintmax_t *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 18) requires 'uintmax_t *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 20) requires 'uintmax_t *' but the argument type is 'void * *'.\n" + "[test.cpp:22]: (warning) %ju in format string (no. 21) requires 'uintmax_t *' but the argument type is 'void *'.\n", errout.str()); + + check("void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu %zu\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:22]: (warning) %zu in format string (no. 1) requires 'size_t *' but the argument type is 'bool *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 2) requires 'size_t *' but the argument type is 'char *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 3) requires 'size_t *' but the argument type is 'signed char *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 4) requires 'size_t *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 5) requires 'size_t *' but the argument type is 'short *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 6) requires 'size_t *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 7) requires 'size_t *' but the argument type is 'int *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 8) requires 'size_t *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 9) requires 'size_t *' but the argument type is 'long *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 10) requires 'size_t *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 11) requires 'size_t *' but the argument type is 'long long *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 12) requires 'size_t *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 13) requires 'size_t *' but the argument type is 'float *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 14) requires 'size_t *' but the argument type is 'double *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 15) requires 'size_t *' but the argument type is 'long double *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 17) requires 'size_t *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 18) requires 'size_t *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 19) requires 'size_t *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 20) requires 'size_t *' but the argument type is 'void * *'.\n" + "[test.cpp:22]: (warning) %zu in format string (no. 21) requires 'size_t *' but the argument type is 'void *'.\n", errout.str()); + + check("void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu %tu\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, &unknown, unknown);\n" + "}\n", false, false, Settings::Unix64); + ASSERT_EQUALS("[test.cpp:22]: (warning) %tu in format string (no. 1) requires 'unsigned ptrdiff_t *' but the argument type is 'bool *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 2) requires 'unsigned ptrdiff_t *' but the argument type is 'char *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 3) requires 'unsigned ptrdiff_t *' but the argument type is 'signed char *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 4) requires 'unsigned ptrdiff_t *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 5) requires 'unsigned ptrdiff_t *' but the argument type is 'short *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 6) requires 'unsigned ptrdiff_t *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 7) requires 'unsigned ptrdiff_t *' but the argument type is 'int *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 8) requires 'unsigned ptrdiff_t *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 9) requires 'unsigned ptrdiff_t *' but the argument type is 'long *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 10) requires 'unsigned ptrdiff_t *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 11) requires 'unsigned ptrdiff_t *' but the argument type is 'long long *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 12) requires 'unsigned ptrdiff_t *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 13) requires 'unsigned ptrdiff_t *' but the argument type is 'float *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 14) requires 'unsigned ptrdiff_t *' but the argument type is 'double *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 15) requires 'unsigned ptrdiff_t *' but the argument type is 'long double *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 16) requires 'unsigned ptrdiff_t *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 17) requires 'unsigned ptrdiff_t *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 18) requires 'unsigned ptrdiff_t *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 19) requires 'unsigned ptrdiff_t *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 20) requires 'unsigned ptrdiff_t *' but the argument type is 'void * *'.\n" + "[test.cpp:22]: (warning) %tu in format string (no. 21) requires 'unsigned ptrdiff_t *' but the argument type is 'void *'.\n", errout.str()); + + check("void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u %I64u\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, &unknown, unknown);\n" + "}\n", false, false, Settings::Unix64); + ASSERT_EQUALS("[test.cpp:22]: (warning) %I64u in format string (no. 1) requires 'unsigned __int64 *' but the argument type is 'bool *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 2) requires 'unsigned __int64 *' but the argument type is 'char *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 3) requires 'unsigned __int64 *' but the argument type is 'signed char *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 4) requires 'unsigned __int64 *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 5) requires 'unsigned __int64 *' but the argument type is 'short *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 6) requires 'unsigned __int64 *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 7) requires 'unsigned __int64 *' but the argument type is 'int *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 8) requires 'unsigned __int64 *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 9) requires 'unsigned __int64 *' but the argument type is 'long *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 10) requires 'unsigned __int64 *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 11) requires 'unsigned __int64 *' but the argument type is 'long long *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 13) requires 'unsigned __int64 *' but the argument type is 'float *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 14) requires 'unsigned __int64 *' but the argument type is 'double *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 15) requires 'unsigned __int64 *' but the argument type is 'long double *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 16) requires 'unsigned __int64 *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 17) requires 'unsigned __int64 *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 18) requires 'unsigned __int64 *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 19) requires 'unsigned __int64 *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 20) requires 'unsigned __int64 *' but the argument type is 'void * *'.\n" + "[test.cpp:22]: (warning) %I64u in format string (no. 21) requires 'unsigned __int64 *' but the argument type is 'void *'.\n", errout.str()); + + check("const int * foo() { }\n" + "void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, \"str\", L\"str\", foo(), &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:23]: (warning) %d in format string (no. 1) requires 'int *' but the argument type is 'bool *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'char *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 3) requires 'int *' but the argument type is 'signed char *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 4) requires 'int *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 5) requires 'int *' but the argument type is 'short *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 6) requires 'int *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 8) requires 'int *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 9) requires 'int *' but the argument type is 'long *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 10) requires 'int *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 11) requires 'int *' but the argument type is 'long long *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 12) requires 'int *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 13) requires 'int *' but the argument type is 'float *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 14) requires 'int *' but the argument type is 'double *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 15) requires 'int *' but the argument type is 'long double *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 16) requires 'int *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 17) requires 'int *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 18) requires 'int *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 19) requires 'int *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 20) requires 'int *' but the argument type is 'void * *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 21) requires 'int *' but the argument type is 'void *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 22) requires 'int *' but the argument type is 'const char *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 23) requires 'int *' but the argument type is 'const wchar_t *'.\n" + "[test.cpp:23]: (warning) %d in format string (no. 24) requires 'int *' but the argument type is 'const int *'.\n", errout.str()); + + check("const unsigned int * foo() { }\n" + "void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, \"str\", L\"str\", foo(), &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:23]: (warning) %x in format string (no. 1) requires 'unsigned int *' but the argument type is 'bool *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 2) requires 'unsigned int *' but the argument type is 'char *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed char *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 4) requires 'unsigned int *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 5) requires 'unsigned int *' but the argument type is 'short *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 6) requires 'unsigned int *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 9) requires 'unsigned int *' but the argument type is 'long *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 10) requires 'unsigned int *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 11) requires 'unsigned int *' but the argument type is 'long long *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 12) requires 'unsigned int *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 13) requires 'unsigned int *' but the argument type is 'float *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 14) requires 'unsigned int *' but the argument type is 'double *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 15) requires 'unsigned int *' but the argument type is 'long double *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 16) requires 'unsigned int *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 17) requires 'unsigned int *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 18) requires 'unsigned int *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 19) requires 'unsigned int *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 20) requires 'unsigned int *' but the argument type is 'void * *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 21) requires 'unsigned int *' but the argument type is 'void *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 22) requires 'unsigned int *' but the argument type is 'const char *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 23) requires 'unsigned int *' but the argument type is 'const wchar_t *'.\n" + "[test.cpp:23]: (warning) %x in format string (no. 24) requires 'unsigned int *' but the argument type is 'const unsigned int *'.\n", errout.str()); + + check("const float * foo() { }\n" + "void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, \"str\", L\"str\", foo(), &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:23]: (warning) %f in format string (no. 1) requires 'float *' but the argument type is 'bool *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 2) requires 'float *' but the argument type is 'char *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 3) requires 'float *' but the argument type is 'signed char *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 4) requires 'float *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 5) requires 'float *' but the argument type is 'short *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 6) requires 'float *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 7) requires 'float *' but the argument type is 'int *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 8) requires 'float *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 9) requires 'float *' but the argument type is 'long *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 10) requires 'float *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 11) requires 'float *' but the argument type is 'long long *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 12) requires 'float *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 14) requires 'float *' but the argument type is 'double *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 15) requires 'float *' but the argument type is 'long double *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 16) requires 'float *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 17) requires 'float *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 18) requires 'float *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 19) requires 'float *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 20) requires 'float *' but the argument type is 'void * *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 21) requires 'float *' but the argument type is 'void *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 22) requires 'float *' but the argument type is 'const char *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 23) requires 'float *' but the argument type is 'const wchar_t *'.\n" + "[test.cpp:23]: (warning) %f in format string (no. 24) requires 'float *' but the argument type is 'const float *'.\n", errout.str()); + + check("const double * foo() { }\n" + "void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, \"str\", L\"str\", foo(), &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:23]: (warning) %lf in format string (no. 1) requires 'double *' but the argument type is 'bool *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 2) requires 'double *' but the argument type is 'char *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 3) requires 'double *' but the argument type is 'signed char *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 4) requires 'double *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 5) requires 'double *' but the argument type is 'short *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 6) requires 'double *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 7) requires 'double *' but the argument type is 'int *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 8) requires 'double *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 9) requires 'double *' but the argument type is 'long *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 10) requires 'double *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 11) requires 'double *' but the argument type is 'long long *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 12) requires 'double *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 13) requires 'double *' but the argument type is 'float *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 15) requires 'double *' but the argument type is 'long double *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 16) requires 'double *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 17) requires 'double *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 18) requires 'double *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 19) requires 'double *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 20) requires 'double *' but the argument type is 'void * *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 21) requires 'double *' but the argument type is 'void *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 22) requires 'double *' but the argument type is 'const char *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 23) requires 'double *' but the argument type is 'const wchar_t *'.\n" + "[test.cpp:23]: (warning) %lf in format string (no. 24) requires 'double *' but the argument type is 'const double *'.\n", errout.str()); + + check("const long double * foo() { }\n" + "void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, \"str\", L\"str\", foo(), &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:23]: (warning) %Lf in format string (no. 1) requires 'long double *' but the argument type is 'bool *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 2) requires 'long double *' but the argument type is 'char *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 3) requires 'long double *' but the argument type is 'signed char *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 4) requires 'long double *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 5) requires 'long double *' but the argument type is 'short *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 6) requires 'long double *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 7) requires 'long double *' but the argument type is 'int *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 8) requires 'long double *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 9) requires 'long double *' but the argument type is 'long *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 10) requires 'long double *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 11) requires 'long double *' but the argument type is 'long long *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 12) requires 'long double *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 13) requires 'long double *' but the argument type is 'float *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 14) requires 'long double *' but the argument type is 'double *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 16) requires 'long double *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 17) requires 'long double *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 18) requires 'long double *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 19) requires 'long double *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 20) requires 'long double *' but the argument type is 'void * *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 21) requires 'long double *' but the argument type is 'void *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 22) requires 'long double *' but the argument type is 'const char *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 23) requires 'long double *' but the argument type is 'const wchar_t *'.\n" + "[test.cpp:23]: (warning) %Lf in format string (no. 24) requires 'long double *' but the argument type is 'const long double *'.\n", errout.str()); + + check("const int * foo() { }\n" + "void foo() {\n" + " bool b;\n" + " char c;\n" + " signed char sc;\n" + " unsigned char uc;\n" + " short s;\n" + " unsigned short us;\n" + " int i;\n" + " unsigned int ui;\n" + " long l;\n" + " unsigned long ul;\n" + " long long ll;\n" + " unsigned long long ull;\n" + " float f;\n" + " double d;\n" + " long double ld;\n" + " size_t st;\n" + " ptrdiff_t pt;\n" + " intmax_t it;\n" + " uintmax_t ut;\n" + " void * vp;\n" + " scanf(\"%n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n %n\",\n" + " &b, &c, &sc, &uc, &s, &us, &i, &ui, &l, &ul, &ll, &ull, &f, &d, &ld, &st, &pt, &it, &ut, &vp, vp, \"str\", L\"str\", foo(), &unknown, unknown);\n" + "}\n", true); + ASSERT_EQUALS("[test.cpp:23]: (warning) %n in format string (no. 1) requires 'int *' but the argument type is 'bool *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 2) requires 'int *' but the argument type is 'char *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 3) requires 'int *' but the argument type is 'signed char *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 4) requires 'int *' but the argument type is 'unsigned char *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 5) requires 'int *' but the argument type is 'short *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 6) requires 'int *' but the argument type is 'unsigned short *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 8) requires 'int *' but the argument type is 'unsigned int *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 9) requires 'int *' but the argument type is 'long *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 10) requires 'int *' but the argument type is 'unsigned long *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 11) requires 'int *' but the argument type is 'long long *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 12) requires 'int *' but the argument type is 'unsigned long long *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 13) requires 'int *' but the argument type is 'float *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 14) requires 'int *' but the argument type is 'double *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 15) requires 'int *' but the argument type is 'long double *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 16) requires 'int *' but the argument type is 'size_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 17) requires 'int *' but the argument type is 'ptrdiff_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 18) requires 'int *' but the argument type is 'intmax_t * {aka long *}'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 19) requires 'int *' but the argument type is 'uintmax_t * {aka unsigned long *}'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 20) requires 'int *' but the argument type is 'void * *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 21) requires 'int *' but the argument type is 'void *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 22) requires 'int *' but the argument type is 'const char *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 23) requires 'int *' but the argument type is 'const wchar_t *'.\n" + "[test.cpp:23]: (warning) %n in format string (no. 24) requires 'int *' but the argument type is 'const int *'.\n", errout.str()); + } void testPrintfArgument() { @@ -631,11 +1380,11 @@ private: " printf(\"%n\", s);\n" " printf(\"%n\", \"s4\");\n" "}"); - ASSERT_EQUALS("[test.cpp:2]: (warning) %n in format string (no. 1) requires a pointer to an non-const integer given in the argument list.\n" - "[test.cpp:3]: (warning) %n in format string (no. 1) requires a pointer to an non-const integer given in the argument list.\n" - "[test.cpp:4]: (warning) %n in format string (no. 1) requires a pointer to an non-const integer given in the argument list.\n" - "[test.cpp:6]: (warning) %n in format string (no. 1) requires a pointer to an non-const integer given in the argument list.\n" - "[test.cpp:7]: (warning) %n in format string (no. 1) requires a pointer to an non-const integer given in the argument list.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (warning) %n in format string (no. 1) requires 'int *' but the argument type is 'const int *'.\n" + "[test.cpp:3]: (warning) %n in format string (no. 1) requires 'int *' but the argument type is 'const int'.\n" + "[test.cpp:4]: (warning) %n in format string (no. 1) requires 'int *' but the argument type is 'int'.\n" + "[test.cpp:6]: (warning) %n in format string (no. 1) requires 'int *' but the argument type is 'std'.\n" + "[test.cpp:7]: (warning) %n in format string (no. 1) requires 'int *' but the argument type is 'const char *'.\n", errout.str()); check("class foo {};\n" "void foo(const int* cpi, foo f, bar b, bar* bp, double d, int i, unsigned int u) {\n" @@ -651,7 +1400,7 @@ private: 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" - "[test.cpp:6]: (warning) %x in format string (no. 1) requires an integer but the argument type is 'int *'.\n" + "[test.cpp:6]: (warning) %x in format string (no. 1) requires an integer but the argument type is 'const int *'.\n" "[test.cpp:8]: (warning) %X in format string (no. 1) requires an integer but the argument type is 'bar *'.\n", errout.str()); check("class foo {};\n" @@ -669,7 +1418,7 @@ private: "[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" - "[test.cpp:7]: (warning) %d in format string (no. 1) requires a signed integer but the argument type is 'int *'.\n" + "[test.cpp:7]: (warning) %d in format string (no. 1) requires a signed integer but the argument type is 'const int *'.\n" "[test.cpp:9]: (warning) %i in format string (no. 1) requires a signed integer but the argument type is 'bar *'.\n", errout.str()); check("class foo {};\n" @@ -687,7 +1436,7 @@ private: "[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" - "[test.cpp:7]: (warning) %u in format string (no. 1) requires an unsigned integer but the argument type is 'int *'.\n" + "[test.cpp:7]: (warning) %u in format string (no. 1) requires an unsigned integer but the argument type is 'const int *'.\n" "[test.cpp:9]: (warning) %u in format string (no. 1) requires an unsigned integer but the argument type is 'bar *'.\n", errout.str()); check("class foo {};\n" @@ -713,7 +1462,7 @@ private: "}"); ASSERT_EQUALS("[test.cpp:3]: (warning) %e in format string (no. 1) requires a 'double' but the argument type is 'foo'.\n" "[test.cpp:4]: (warning) %E in format string (no. 1) requires a 'double' but the argument type is 'const char *'.\n" - "[test.cpp:5]: (warning) %f in format string (no. 1) requires a 'double' but the argument type is 'int *'.\n" + "[test.cpp:5]: (warning) %f in format string (no. 1) requires a 'double' but the argument type is 'const int *'.\n" "[test.cpp:6]: (warning) %G in format string (no. 1) requires a 'double' but the argument type is 'bar *'.\n", errout.str()); check("class foo;\n"