diff --git a/lib/checkio.cpp b/lib/checkio.cpp index a0591bc4c..609a9542d 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -1366,10 +1366,15 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * tok, const Settings *settings, // 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 (!Token::Match(tok, "&| %str%|%num%|%name% ,|)") && !Token::Match(tok, "%name% [|(|.|<|::|?")) { + if (!Token::Match(tok, "&| %str%|%name% ,|)") && !Token::Match(tok, "%name% [|(|.|<|::|?")) { const ValueType *valuetype = tok->argumentType(); if (valuetype && valuetype->type >= ValueType::Type::BOOL) { - tempToken = new Token(0); + typeToken = tempToken = new Token(0); + if (valuetype->constness & 1) { + tempToken->str("const"); + tempToken->insertToken("a"); + tempToken = tempToken->next(); + } if (valuetype->pointer == 0U && valuetype->type <= ValueType::INT) tempToken->str("int"); else if (valuetype->type == ValueType::BOOL) @@ -1397,7 +1402,7 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * tok, const Settings *settings, } for (unsigned int p = 0; p < valuetype->pointer; p++) tempToken->insertToken("*"); - typeToken = tempToken; + tempToken = const_cast(typeToken); return; } } diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index fef1cb033..7633332a4 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3650,9 +3650,9 @@ bool SymbolDatabase::isReservedName(const std::string& iName) const return (c_keywords.find(iName) != c_keywords.cend()) || (isCPP() && (cpp_keywords.find(iName) != cpp_keywords.cend())); } -static void setValueType(Token *tok, ValueType::Sign sign, ValueType::Type type, unsigned int pointer) +static void setValueType(Token *tok, ValueType::Sign sign, ValueType::Type type, unsigned int pointer, unsigned int constness = 0U) { - tok->setValueType(new ValueType(sign,type,pointer)); + tok->setValueType(new ValueType(sign,type,pointer,constness)); Token *parent = const_cast(tok->astParent()); if (!parent || parent->valueType()) return; @@ -3660,11 +3660,11 @@ static void setValueType(Token *tok, ValueType::Sign sign, ValueType::Type type, return; if (parent->str() == "[" && pointer > 0U) { - setValueType(parent, sign, type, pointer - 1U); + setValueType(parent, sign, type, pointer - 1U, constness >> 1); return; } if (parent->str() == "*" && !parent->astOperand2() && pointer > 0U) { - setValueType(parent, sign, type, pointer - 1U); + setValueType(parent, sign, type, pointer - 1U, constness >> 1); return; } @@ -3674,17 +3674,17 @@ static void setValueType(Token *tok, ValueType::Sign sign, ValueType::Type type, const ValueType *vt2 = parent->astOperand2() ? parent->astOperand2()->valueType() : nullptr; if (parent->isArithmeticalOp() && vt2) { if (vt1->pointer != 0U && vt2->pointer == 0U) { - setValueType(parent, vt1->sign, vt1->type, vt1->pointer); + setValueType(parent, vt1->sign, vt1->type, vt1->pointer, vt1->constness); return; } if (vt1->pointer == 0U && vt2->pointer != 0U) { - setValueType(parent, vt2->sign, vt2->type, vt2->pointer); + setValueType(parent, vt2->sign, vt2->type, vt2->pointer, vt2->constness); return; } if (vt1->pointer != 0U) { // result is pointer diff - setValueType(parent, ValueType::Sign::UNSIGNED, ValueType::Type::INT, 0U); + setValueType(parent, ValueType::Sign::UNSIGNED, ValueType::Type::INT, 0U, 0U); return; } @@ -3789,7 +3789,7 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens) else if (tok->tokType() == Token::eChar) ::setValueType(tok, ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U); else if (tok->tokType() == Token::eString) - ::setValueType(tok, ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 1U); + ::setValueType(tok, ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 1U, 1U); else if (tok->str() == "(") { // cast if (!tok->astOperand2() && Token::Match(tok, "( %name%")) { @@ -3810,28 +3810,33 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens) std::string ValueType::str() const { std::string ret; + if (constness & 1) + ret = " const"; if (isIntegral()) { if (sign == SIGNED) - ret = "signed "; + ret += " signed"; else if (sign == UNSIGNED) - ret = "unsigned "; + ret += " unsigned"; if (type == BOOL) - ret += "bool"; + ret += " bool"; else if (type == CHAR) - ret += "char"; + ret += " char"; else if (type == SHORT) - ret += "short"; + ret += " short"; else if (type == INT) - ret += "int"; + ret += " int"; else if (type == LONG) - ret += "long"; + ret += " long"; else if (type == LONGLONG) - ret += "long long"; + ret += " long long"; } else if (type == FLOAT) - ret = "float"; + ret = " float"; else if (type == DOUBLE) - ret = "double"; - for (unsigned int p = 0; p < pointer; p++) - ret += "*"; - return ret; + ret = " double"; + for (unsigned int p = 0; p < pointer; p++) { + ret += " *"; + if (constness & (2 << p)) + ret += " const"; + } + return ret.substr(1); } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index d828b348b..71ef84575 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1044,9 +1044,11 @@ public: enum Sign {UNKNOWN_SIGN, SIGNED, UNSIGNED} sign; enum Type {UNKNOWN_TYPE, NONSTD, BOOL, CHAR, SHORT, INT, LONG, LONGLONG, FLOAT, DOUBLE} type; unsigned int pointer; // 0=>not pointer, 1=>*, 2=>**, 3=>***, etc + unsigned int constness; // bit 0=data, bit 1=*, bit 2=** - ValueType() : sign(UNKNOWN_SIGN), type(UNKNOWN_TYPE), pointer(0U) {} - ValueType(enum Sign s, enum Type t, unsigned int p) : sign(s), type(t), pointer(p) {} + ValueType() : sign(UNKNOWN_SIGN), type(UNKNOWN_TYPE), pointer(0U), constness(0U) {} + ValueType(enum Sign s, enum Type t, unsigned int p) : sign(s), type(t), pointer(p), constness(0U) {} + ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c) : sign(s), type(t), pointer(p), constness(c) {} bool isIntegral() const { return (type >= ValueType::Type::BOOL && type <= ValueType::Type::LONGLONG); diff --git a/test/testio.cpp b/test/testio.cpp index 9c9f0a378..a4f8a0e05 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -2317,11 +2317,11 @@ private: void testPrintfArgument() { check("void foo() {\n" - " printf(\"%u\");\n" - " printf(\"%u%s\", 123);\n" - " printf(\"%u%s%d\", 0, bar());\n" - " printf(\"%u%%%s%d\", 0, bar());\n" - " printf(\"%udfd%%dfa%s%d\", 0, bar());\n" + " printf(\"%i\");\n" + " printf(\"%i%s\", 123);\n" + " printf(\"%i%s%d\", 0, bar());\n" + " printf(\"%i%%%s%d\", 0, bar());\n" + " printf(\"%idfd%%dfa%s%d\", 0, bar());\n" " fprintf(stderr,\"%u%s\");\n" " snprintf(str,10,\"%u%s\");\n" " sprintf(string1, \"%-*.*s\", 32, string2);\n" // #3364 @@ -2339,28 +2339,28 @@ private: check("void foo(char *str) {\n" " printf(\"\", 0);\n" - " printf(\"%u\", 123, bar());\n" - " printf(\"%u%s\", 0, bar(), 43123);\n" + " printf(\"%i\", 123, bar());\n" + " printf(\"%i%s\", 0, bar(), 43123);\n" "}"); ASSERT_EQUALS("[test.cpp:2]: (warning) printf format string requires 0 parameters but 1 is given.\n" "[test.cpp:3]: (warning) printf format string requires 1 parameter but 2 are given.\n" "[test.cpp:4]: (warning) printf format string requires 2 parameters but 3 are given.\n", errout.str()); check("void foo() {\n" // swprintf exists as MSVC extension and as standard function: #4790 - " swprintf(string1, L\"%u\", 32, string2);\n" // MSVC implementation + " swprintf(string1, L\"%i\", 32, string2);\n" // MSVC implementation " swprintf(string1, L\"%s%s\", L\"a\", string2);\n" // MSVC implementation - " swprintf(string1, 6, L\"%u\", 32, string2);\n" // Standard implementation - " swprintf(string1, 6, L\"%u%s\", 32, string2);\n" // Standard implementation + " swprintf(string1, 6, L\"%i\", 32, string2);\n" // Standard implementation + " swprintf(string1, 6, L\"%i%s\", 32, string2);\n" // Standard implementation "}"); ASSERT_EQUALS("[test.cpp:2]: (warning) swprintf format string requires 1 parameter but 2 are given.\n" "[test.cpp:4]: (warning) swprintf format string requires 1 parameter but 2 are given.\n", errout.str()); check("void foo(char *str) {\n" - " printf(\"%u\", 0);\n" - " printf(\"%u%s\", 123, bar());\n" - " printf(\"%u%s%d\", 0, bar(), 43123);\n" - " printf(\"%u%%%s%d\", 0, bar(), 43123);\n" - " printf(\"%udfd%%dfa%s%d\", 0, bar(), 43123);\n" + " printf(\"%i\", 0);\n" + " printf(\"%i%s\", 123, bar());\n" + " printf(\"%i%s%d\", 0, bar(), 43123);\n" + " printf(\"%i%%%s%d\", 0, bar(), 43123);\n" + " printf(\"%idfd%%dfa%s%d\", 0, bar(), 43123);\n" " printf(\"%\"PRId64\"\n\", 123);\n" " fprintf(stderr,\"%\"PRId64\"\n\", 123);\n" " snprintf(str,10,\"%\"PRId64\"\n\", 123);\n" diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 891ad558d..52ae547a9 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -2972,7 +2972,7 @@ private: ASSERT_EQUALS("float", typeOf("1 + 2.3f", "+")); // char * - ASSERT_EQUALS("char*", typeOf("\"hello\" + 1", "+")); + ASSERT_EQUALS("const char *", typeOf("\"hello\" + 1", "+")); ASSERT_EQUALS("char", typeOf("\"hello\"[1]", "[")); ASSERT_EQUALS("char", typeOf("*\"hello\"", "*")); @@ -2988,7 +2988,7 @@ private: ASSERT_EQUALS("unsigned int", typeOf("unsigned int u1, u2; a = u1 * u2;", "u1 *")); // array.. - ASSERT_EQUALS("int*", typeOf("int x[10]; a = x + 1;", "+")); + ASSERT_EQUALS("int *", typeOf("int x[10]; a = x + 1;", "+")); ASSERT_EQUALS("int", typeOf("int x[10]; a = x[0] + 1;", "+")); // cast.. @@ -2996,6 +2996,9 @@ private: ASSERT_EQUALS("long", typeOf("a = (long)32;", "(")); ASSERT_EQUALS("long", typeOf("a = (long int)32;", "(")); ASSERT_EQUALS("long long", typeOf("a = (long long)32;", "(")); + + // const.. + ASSERT_EQUALS("const char *", typeOf("a = \"123\";", "\"123\"")); } };