Fixed #4902 (printf and scanf format checks don't support microsoft %I, %I32 and %I64 extensions)
This commit is contained in:
parent
5aa79198e6
commit
56d8073d0f
|
@ -682,32 +682,23 @@ void CheckIO::checkWrongPrintfScanfArguments()
|
|||
}
|
||||
break;
|
||||
case 'I': // Microsoft extension: I for size_t and ptrdiff_t, I32 for __int32, and I64 for __int64
|
||||
if (i != formatString.end()) {
|
||||
if (isalpha(*(i+1))) {
|
||||
specifier = *i++;
|
||||
} else if (*(i+1) == '3' && *(i+2) == '2' && isalpha(*(i+3))) {
|
||||
specifier = *i++;
|
||||
specifier += *i++;
|
||||
specifier += *i++;
|
||||
} else if (*(i+1) == '6' && *(i+2) == '4' && isalpha(*(i+3))) {
|
||||
specifier = *i++;
|
||||
specifier += *i++;
|
||||
specifier += *i++;
|
||||
}
|
||||
if ((*(i+1) == '3' && *(i+2) == '2') ||
|
||||
(*(i+1) == '6' && *(i+2) == '4')) {
|
||||
specifier += *i++;
|
||||
specifier += *i++;
|
||||
}
|
||||
break;
|
||||
// fallthrough
|
||||
case 'j': // intmax_t or uintmax_t
|
||||
case 'z': // size_t
|
||||
case 't': // ptrdiff_t
|
||||
case 'L': // long double
|
||||
// Expect an alphabetical character after these specifiers
|
||||
if (i != formatString.end() && !isalpha(*(i+1))) {
|
||||
std::string modifier;
|
||||
modifier += *i;
|
||||
invalidLengthModifierError(tok, numFormat, modifier);
|
||||
specifier += *i;
|
||||
invalidLengthModifierError(tok, numFormat, specifier);
|
||||
done = true;
|
||||
} else {
|
||||
specifier = *i++;
|
||||
specifier += *i++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -92,7 +92,7 @@ private:
|
|||
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 invalidLengthModifierError(const Token* tok, unsigned int numFormat,const std::string& modifier);
|
||||
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);
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||
|
|
|
@ -840,6 +840,39 @@ private:
|
|||
"[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 integer given in the argument list.\n"
|
||||
"[test.cpp:13]: (warning) %I64d in format string (no. 1) requires a signed integer given in the argument list.\n", errout.str());
|
||||
|
||||
check("void foo() {\n"
|
||||
" size_t s;\n"
|
||||
" int i;\n"
|
||||
" printf(\"%I\", s);\n"
|
||||
" printf(\"%I6\", s);\n"
|
||||
" printf(\"%I6x\", s);\n"
|
||||
" printf(\"%I16\", s);\n"
|
||||
" printf(\"%I16x\", s);\n"
|
||||
" printf(\"%I32\", s);\n"
|
||||
" printf(\"%I64\", s);\n"
|
||||
" printf(\"%I%i\", s, i);\n"
|
||||
" printf(\"%I6%i\", s, i);\n"
|
||||
" printf(\"%I6x%i\", s, i);\n"
|
||||
" printf(\"%I16%i\", s, i);\n"
|
||||
" printf(\"%I16x%i\", s, i);\n"
|
||||
" printf(\"%I32%i\", s, i);\n"
|
||||
" printf(\"%I64%i\", s, i);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:6]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:7]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:8]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:9]: (warning) 'I32' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:10]: (warning) 'I64' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:11]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:12]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:13]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:14]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:15]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:16]: (warning) 'I32' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n"
|
||||
"[test.cpp:17]: (warning) 'I64' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier.\n", errout.str());
|
||||
}
|
||||
|
||||
void testlibrarycfg() {
|
||||
|
|
Loading…
Reference in New Issue