Fixed #7014 (False positive for printf("%c", "hello"[0]))
This commit is contained in:
parent
73b088a6dd
commit
8f6bd7fd0d
|
@ -1361,6 +1361,33 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * tok, const Settings *settings,
|
|||
, address(false)
|
||||
, isCPP(_isCPP)
|
||||
{
|
||||
// Use AST type info
|
||||
// TODO: This is a bailout so that old code is used in simple cases. Remove the old code and always use the AST type.
|
||||
if (tok && !Token::Match(tok, "&| %str%|%num%|%name% ,|)") && !Token::Match(tok, "%name% [|(|.|<|::|?")) {
|
||||
const ValueType *valuetype = tok->argumentType();
|
||||
if (valuetype && valuetype->type >= ValueType::Type::BOOL && !valuetype->pointer) {
|
||||
tempToken = new Token(0);
|
||||
if (valuetype->type <= ValueType::INT)
|
||||
tempToken->str("int");
|
||||
else if (valuetype->type == ValueType::LONG)
|
||||
tempToken->str("long");
|
||||
else if (valuetype->type == ValueType::LONGLONG)
|
||||
tempToken->str("long");
|
||||
else if (valuetype->type == ValueType::FLOAT)
|
||||
tempToken->str("float");
|
||||
else if (valuetype->type == ValueType::DOUBLE)
|
||||
tempToken->str("double");
|
||||
if (valuetype->isIntegral()) {
|
||||
if (valuetype->sign == ValueType::Sign::UNSIGNED)
|
||||
tempToken->isUnsigned(true);
|
||||
else if (valuetype->sign == ValueType::Sign::SIGNED)
|
||||
tempToken->isSigned(true);
|
||||
}
|
||||
typeToken = tempToken;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (tok) {
|
||||
if (tok->tokType() == Token::eString) {
|
||||
typeToken = tok;
|
||||
|
|
|
@ -229,6 +229,13 @@ public:
|
|||
}
|
||||
void setValueType(ValueType *vt);
|
||||
|
||||
const ValueType *argumentType() const {
|
||||
const Token *top = this;
|
||||
while (top && !Token::Match(top->astParent(), ",|("))
|
||||
top = top->astParent();
|
||||
return top ? top->valuetype : nullptr;
|
||||
}
|
||||
|
||||
Token::Type tokType() const {
|
||||
return _tokType;
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ private:
|
|||
|
||||
TEST_CASE(testTernary); // ticket #6182
|
||||
TEST_CASE(testUnsignedConst); // ticket #6132
|
||||
|
||||
TEST_CASE(testAstType); // #7014
|
||||
}
|
||||
|
||||
void check(const char code[], bool inconclusive = false, bool portability = false, Settings::PlatformType platform = Settings::Unspecified) {
|
||||
|
@ -2781,7 +2783,7 @@ private:
|
|||
" printf(\"%s\", newline ? a : str + len);\n"
|
||||
" printf(\"%s\", newline + newline);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) %s in format string (no. 1) requires 'char *' but the argument type is 'int'.\n", errout.str());
|
||||
|
||||
check("struct Fred { int i; } f;\n"
|
||||
"struct Fred & bar() { };\n"
|
||||
|
@ -3723,6 +3725,12 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void testAstType() { // ticket #7014
|
||||
check("void test() {\n"
|
||||
" printf(\"%c\", \"hello\"[0]);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestIO)
|
||||
|
|
Loading…
Reference in New Issue