ValueType: Handling constness

This commit is contained in:
Daniel Marjamäki 2015-10-07 19:08:26 +02:00
parent b7f2f826a4
commit 604a9acb48
5 changed files with 58 additions and 43 deletions

View File

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

View File

@ -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,28 +3810,33 @@ 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)
ret += "char"; ret += " char";
else if (type == SHORT) else if (type == SHORT)
ret += "short"; ret += " short";
else if (type == INT) else if (type == INT)
ret += "int"; ret += " int";
else if (type == LONG) else if (type == LONG)
ret += "long"; ret += " long";
else if (type == LONGLONG) else if (type == LONGLONG)
ret += "long long"; ret += " long long";
} else if (type == FLOAT) } else if (type == FLOAT)
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);
} }

View File

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

View File

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

View File

@ -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\"", "*"));
@ -2988,7 +2988,7 @@ private:
ASSERT_EQUALS("unsigned int", typeOf("unsigned int u1, u2; a = u1 * u2;", "u1 *")); ASSERT_EQUALS("unsigned int", typeOf("unsigned int u1, u2; a = u1 * u2;", "u1 *"));
// array.. // 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;", "+")); ASSERT_EQUALS("int", typeOf("int x[10]; a = x[0] + 1;", "+"));
// cast.. // cast..
@ -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\""));
} }
}; };