ValueType: Handling constness
This commit is contained in:
parent
b7f2f826a4
commit
604a9acb48
|
@ -1366,10 +1366,15 @@ CheckIO::ArgumentInfo::ArgumentInfo(const Token * tok, const Settings *settings,
|
||||||
|
|
||||||
// Use AST type info
|
// 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.
|
// 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();
|
const ValueType *valuetype = tok->argumentType();
|
||||||
if (valuetype && valuetype->type >= ValueType::Type::BOOL) {
|
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)
|
if (valuetype->pointer == 0U && valuetype->type <= ValueType::INT)
|
||||||
tempToken->str("int");
|
tempToken->str("int");
|
||||||
else if (valuetype->type == ValueType::BOOL)
|
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++)
|
for (unsigned int p = 0; p < valuetype->pointer; p++)
|
||||||
tempToken->insertToken("*");
|
tempToken->insertToken("*");
|
||||||
typeToken = tempToken;
|
tempToken = const_cast<Token*>(typeToken);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()));
|
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<Token *>(tok->astParent());
|
Token *parent = const_cast<Token *>(tok->astParent());
|
||||||
if (!parent || parent->valueType())
|
if (!parent || parent->valueType())
|
||||||
return;
|
return;
|
||||||
|
@ -3660,11 +3660,11 @@ static void setValueType(Token *tok, ValueType::Sign sign, ValueType::Type type,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (parent->str() == "[" && pointer > 0U) {
|
if (parent->str() == "[" && pointer > 0U) {
|
||||||
setValueType(parent, sign, type, pointer - 1U);
|
setValueType(parent, sign, type, pointer - 1U, constness >> 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parent->str() == "*" && !parent->astOperand2() && pointer > 0U) {
|
if (parent->str() == "*" && !parent->astOperand2() && pointer > 0U) {
|
||||||
setValueType(parent, sign, type, pointer - 1U);
|
setValueType(parent, sign, type, pointer - 1U, constness >> 1);
|
||||||
return;
|
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;
|
const ValueType *vt2 = parent->astOperand2() ? parent->astOperand2()->valueType() : nullptr;
|
||||||
if (parent->isArithmeticalOp() && vt2) {
|
if (parent->isArithmeticalOp() && vt2) {
|
||||||
if (vt1->pointer != 0U && vt2->pointer == 0U) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vt1->pointer == 0U && vt2->pointer != 0U) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vt1->pointer != 0U) { // result is pointer diff
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3789,7 +3789,7 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens)
|
||||||
else if (tok->tokType() == Token::eChar)
|
else if (tok->tokType() == Token::eChar)
|
||||||
::setValueType(tok, ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U);
|
::setValueType(tok, ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U);
|
||||||
else if (tok->tokType() == Token::eString)
|
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() == "(") {
|
else if (tok->str() == "(") {
|
||||||
// cast
|
// cast
|
||||||
if (!tok->astOperand2() && Token::Match(tok, "( %name%")) {
|
if (!tok->astOperand2() && Token::Match(tok, "( %name%")) {
|
||||||
|
@ -3810,11 +3810,13 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens)
|
||||||
std::string ValueType::str() const
|
std::string ValueType::str() const
|
||||||
{
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
if (constness & 1)
|
||||||
|
ret = " const";
|
||||||
if (isIntegral()) {
|
if (isIntegral()) {
|
||||||
if (sign == SIGNED)
|
if (sign == SIGNED)
|
||||||
ret = "signed ";
|
ret += " signed";
|
||||||
else if (sign == UNSIGNED)
|
else if (sign == UNSIGNED)
|
||||||
ret = "unsigned ";
|
ret += " unsigned";
|
||||||
if (type == BOOL)
|
if (type == BOOL)
|
||||||
ret += " bool";
|
ret += " bool";
|
||||||
else if (type == CHAR)
|
else if (type == CHAR)
|
||||||
|
@ -3831,7 +3833,10 @@ std::string ValueType::str() const
|
||||||
ret = " float";
|
ret = " float";
|
||||||
else if (type == DOUBLE)
|
else if (type == DOUBLE)
|
||||||
ret = " double";
|
ret = " double";
|
||||||
for (unsigned int p = 0; p < pointer; p++)
|
for (unsigned int p = 0; p < pointer; p++) {
|
||||||
ret += " *";
|
ret += " *";
|
||||||
return ret;
|
if (constness & (2 << p))
|
||||||
|
ret += " const";
|
||||||
|
}
|
||||||
|
return ret.substr(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1044,9 +1044,11 @@ public:
|
||||||
enum Sign {UNKNOWN_SIGN, SIGNED, UNSIGNED} sign;
|
enum Sign {UNKNOWN_SIGN, SIGNED, UNSIGNED} sign;
|
||||||
enum Type {UNKNOWN_TYPE, NONSTD, BOOL, CHAR, SHORT, INT, LONG, LONGLONG, FLOAT, DOUBLE} type;
|
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 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() : 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) {}
|
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 {
|
bool isIntegral() const {
|
||||||
return (type >= ValueType::Type::BOOL && type <= ValueType::Type::LONGLONG);
|
return (type >= ValueType::Type::BOOL && type <= ValueType::Type::LONGLONG);
|
||||||
|
|
|
@ -2317,11 +2317,11 @@ private:
|
||||||
|
|
||||||
void testPrintfArgument() {
|
void testPrintfArgument() {
|
||||||
check("void foo() {\n"
|
check("void foo() {\n"
|
||||||
" printf(\"%u\");\n"
|
" printf(\"%i\");\n"
|
||||||
" printf(\"%u%s\", 123);\n"
|
" printf(\"%i%s\", 123);\n"
|
||||||
" printf(\"%u%s%d\", 0, bar());\n"
|
" printf(\"%i%s%d\", 0, bar());\n"
|
||||||
" printf(\"%u%%%s%d\", 0, bar());\n"
|
" printf(\"%i%%%s%d\", 0, bar());\n"
|
||||||
" printf(\"%udfd%%dfa%s%d\", 0, bar());\n"
|
" printf(\"%idfd%%dfa%s%d\", 0, bar());\n"
|
||||||
" fprintf(stderr,\"%u%s\");\n"
|
" fprintf(stderr,\"%u%s\");\n"
|
||||||
" snprintf(str,10,\"%u%s\");\n"
|
" snprintf(str,10,\"%u%s\");\n"
|
||||||
" sprintf(string1, \"%-*.*s\", 32, string2);\n" // #3364
|
" sprintf(string1, \"%-*.*s\", 32, string2);\n" // #3364
|
||||||
|
@ -2339,28 +2339,28 @@ private:
|
||||||
|
|
||||||
check("void foo(char *str) {\n"
|
check("void foo(char *str) {\n"
|
||||||
" printf(\"\", 0);\n"
|
" printf(\"\", 0);\n"
|
||||||
" printf(\"%u\", 123, bar());\n"
|
" printf(\"%i\", 123, bar());\n"
|
||||||
" printf(\"%u%s\", 0, bar(), 43123);\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"
|
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: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());
|
"[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
|
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, L\"%s%s\", L\"a\", string2);\n" // MSVC implementation
|
||||||
" swprintf(string1, 6, L\"%u\", 32, string2);\n" // Standard implementation
|
" swprintf(string1, 6, L\"%i\", 32, string2);\n" // Standard implementation
|
||||||
" swprintf(string1, 6, L\"%u%s\", 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"
|
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());
|
"[test.cpp:4]: (warning) swprintf format string requires 1 parameter but 2 are given.\n", errout.str());
|
||||||
|
|
||||||
check("void foo(char *str) {\n"
|
check("void foo(char *str) {\n"
|
||||||
" printf(\"%u\", 0);\n"
|
" printf(\"%i\", 0);\n"
|
||||||
" printf(\"%u%s\", 123, bar());\n"
|
" printf(\"%i%s\", 123, bar());\n"
|
||||||
" printf(\"%u%s%d\", 0, bar(), 43123);\n"
|
" printf(\"%i%s%d\", 0, bar(), 43123);\n"
|
||||||
" printf(\"%u%%%s%d\", 0, bar(), 43123);\n"
|
" printf(\"%i%%%s%d\", 0, bar(), 43123);\n"
|
||||||
" printf(\"%udfd%%dfa%s%d\", 0, bar(), 43123);\n"
|
" printf(\"%idfd%%dfa%s%d\", 0, bar(), 43123);\n"
|
||||||
" printf(\"%\"PRId64\"\n\", 123);\n"
|
" printf(\"%\"PRId64\"\n\", 123);\n"
|
||||||
" fprintf(stderr,\"%\"PRId64\"\n\", 123);\n"
|
" fprintf(stderr,\"%\"PRId64\"\n\", 123);\n"
|
||||||
" snprintf(str,10,\"%\"PRId64\"\n\", 123);\n"
|
" snprintf(str,10,\"%\"PRId64\"\n\", 123);\n"
|
||||||
|
|
|
@ -2972,7 +2972,7 @@ private:
|
||||||
ASSERT_EQUALS("float", typeOf("1 + 2.3f", "+"));
|
ASSERT_EQUALS("float", typeOf("1 + 2.3f", "+"));
|
||||||
|
|
||||||
// char *
|
// 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\"[1]", "["));
|
||||||
ASSERT_EQUALS("char", typeOf("*\"hello\"", "*"));
|
ASSERT_EQUALS("char", typeOf("*\"hello\"", "*"));
|
||||||
|
|
||||||
|
@ -2996,6 +2996,9 @@ private:
|
||||||
ASSERT_EQUALS("long", typeOf("a = (long)32;", "("));
|
ASSERT_EQUALS("long", typeOf("a = (long)32;", "("));
|
||||||
ASSERT_EQUALS("long", typeOf("a = (long int)32;", "("));
|
ASSERT_EQUALS("long", typeOf("a = (long int)32;", "("));
|
||||||
ASSERT_EQUALS("long long", typeOf("a = (long long)32;", "("));
|
ASSERT_EQUALS("long long", typeOf("a = (long long)32;", "("));
|
||||||
|
|
||||||
|
// const..
|
||||||
|
ASSERT_EQUALS("const char *", typeOf("a = \"123\";", "\"123\""));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue