diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 62ee75b3a..6a662b074 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -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; diff --git a/lib/token.h b/lib/token.h index 71c3975db..9bdf43891 100644 --- a/lib/token.h +++ b/lib/token.h @@ -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; } diff --git a/test/testio.cpp b/test/testio.cpp index 6073dcd93..1d6e013dd 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -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)