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;
|
break;
|
||||||
case 'I': // Microsoft extension: I for size_t and ptrdiff_t, I32 for __int32, and I64 for __int64
|
case 'I': // Microsoft extension: I for size_t and ptrdiff_t, I32 for __int32, and I64 for __int64
|
||||||
if (i != formatString.end()) {
|
if ((*(i+1) == '3' && *(i+2) == '2') ||
|
||||||
if (isalpha(*(i+1))) {
|
(*(i+1) == '6' && *(i+2) == '4')) {
|
||||||
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++;
|
||||||
specifier += *i++;
|
specifier += *i++;
|
||||||
}
|
}
|
||||||
}
|
// fallthrough
|
||||||
break;
|
|
||||||
case 'j': // intmax_t or uintmax_t
|
case 'j': // intmax_t or uintmax_t
|
||||||
case 'z': // size_t
|
case 'z': // size_t
|
||||||
case 't': // ptrdiff_t
|
case 't': // ptrdiff_t
|
||||||
case 'L': // long double
|
case 'L': // long double
|
||||||
// Expect an alphabetical character after these specifiers
|
// Expect an alphabetical character after these specifiers
|
||||||
if (i != formatString.end() && !isalpha(*(i+1))) {
|
if (i != formatString.end() && !isalpha(*(i+1))) {
|
||||||
std::string modifier;
|
specifier += *i;
|
||||||
modifier += *i;
|
invalidLengthModifierError(tok, numFormat, specifier);
|
||||||
invalidLengthModifierError(tok, numFormat, modifier);
|
|
||||||
done = true;
|
done = true;
|
||||||
} else {
|
} else {
|
||||||
specifier = *i++;
|
specifier += *i++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -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: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: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());
|
"[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() {
|
void testlibrarycfg() {
|
||||||
|
|
Loading…
Reference in New Issue