Fixed #7014 (False positive for printf("%c", "hello"[0]))

This commit is contained in:
Daniel Marjamäki 2015-10-05 10:12:30 +02:00
parent 73b088a6dd
commit 8f6bd7fd0d
3 changed files with 43 additions and 1 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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)