ValueType: Added support for static member variables and simplified code
This commit is contained in:
parent
b801386ac8
commit
cae19cadd3
|
@ -3676,12 +3676,15 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value
|
||||||
Token *parent = const_cast<Token *>(tok->astParent());
|
Token *parent = const_cast<Token *>(tok->astParent());
|
||||||
if (!parent || parent->valueType())
|
if (!parent || parent->valueType())
|
||||||
return;
|
return;
|
||||||
if (!parent->astOperand1() || !parent->astOperand1()->valueType())
|
if (!parent->astOperand1())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Token::Match(parent, "<<|>>")) {
|
const ValueType *vt1 = parent->astOperand1() ? parent->astOperand1()->valueType() : nullptr;
|
||||||
if (!cpp || (parent->astOperand2() && parent->astOperand2()->valueType() && parent->astOperand2()->valueType()->isIntegral()))
|
const ValueType *vt2 = parent->astOperand2() ? parent->astOperand2()->valueType() : nullptr;
|
||||||
setValueType(parent, *parent->astOperand1()->valueType(), cpp, defaultSignedness);
|
|
||||||
|
if (vt1 && Token::Match(parent, "<<|>>")) {
|
||||||
|
if (!cpp || (vt2 && vt2->isIntegral()))
|
||||||
|
setValueType(parent, *vt1, cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3706,26 +3709,31 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent->str() == "." &&
|
if ((parent->str() == "." || parent->str() == "::") &&
|
||||||
valuetype.typeScope &&
|
parent->astOperand2() && parent->astOperand2()->isName()) {
|
||||||
parent->astOperand2() && parent->astOperand2()->isName() && !parent->astOperand2()->valueType()) {
|
const Variable* var = parent->astOperand2()->variable();
|
||||||
|
if (!var && valuetype.typeScope && vt1) {
|
||||||
const std::string &name = parent->astOperand2()->str();
|
const std::string &name = parent->astOperand2()->str();
|
||||||
const Scope *typeScope = parent->astOperand1()->valueType()->typeScope;
|
const Scope *typeScope = vt1->typeScope;
|
||||||
if (!typeScope)
|
if (!typeScope)
|
||||||
return;
|
return;
|
||||||
for (std::list<Variable>::const_iterator it = typeScope->varlist.begin(); it != typeScope->varlist.end(); ++it) {
|
for (std::list<Variable>::const_iterator it = typeScope->varlist.begin(); it != typeScope->varlist.end(); ++it) {
|
||||||
const Variable &var = *it;
|
if (it->nameToken()->str() == name) {
|
||||||
if (var.nameToken()->str() == name) {
|
var = &*it;
|
||||||
setValueType(parent, var, cpp, defaultSignedness);
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (var)
|
||||||
|
setValueType(parent, *var, cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent->astOperand2() && !parent->astOperand2()->valueType())
|
if (!vt1)
|
||||||
return;
|
return;
|
||||||
const ValueType *vt1 = parent->astOperand1()->valueType();
|
if (parent->astOperand2() && !vt2)
|
||||||
const ValueType *vt2 = parent->astOperand2() ? parent->astOperand2()->valueType() : nullptr;
|
return;
|
||||||
|
|
||||||
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, cpp, defaultSignedness);
|
setValueType(parent, *vt1, cpp, defaultSignedness);
|
||||||
|
|
|
@ -1648,11 +1648,11 @@ private:
|
||||||
" f[0].d, f[0].baz.i, f[0].bar[0].i);\n"
|
" f[0].d, f[0].baz.i, f[0].bar[0].i);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:13]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'double'.\n"
|
ASSERT_EQUALS("[test.cpp:13]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'double'.\n"
|
||||||
"[test.cpp:13]: (warning) %f in format string (no. 2) requires 'double' but the argument type is 'int'.\n"
|
"[test.cpp:13]: (warning) %f in format string (no. 2) requires 'double' but the argument type is 'signed int'.\n"
|
||||||
"[test.cpp:13]: (warning) %f in format string (no. 3) requires 'double' but the argument type is 'signed int'.\n"
|
"[test.cpp:13]: (warning) %f in format string (no. 3) requires 'double' but the argument type is 'signed int'.\n"
|
||||||
"[test.cpp:13]: (warning) %d in format string (no. 4) requires 'int' but the argument type is 'double'.\n"
|
"[test.cpp:13]: (warning) %d in format string (no. 4) requires 'int' but the argument type is 'double'.\n"
|
||||||
"[test.cpp:13]: (warning) %f in format string (no. 5) requires 'double' but the argument type is 'int'.\n"
|
"[test.cpp:13]: (warning) %f in format string (no. 5) requires 'double' but the argument type is 'signed int'.\n"
|
||||||
"[test.cpp:13]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'int'.\n", errout.str());
|
"[test.cpp:13]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'signed int'.\n", errout.str());
|
||||||
|
|
||||||
check("short f() { return 0; }\n"
|
check("short f() { return 0; }\n"
|
||||||
"void foo() { printf(\"%d %u %lu %I64u %I64d %f %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f()); }");
|
"void foo() { printf(\"%d %u %lu %I64u %I64d %f %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f()); }");
|
||||||
|
|
|
@ -49,6 +49,7 @@ private:
|
||||||
const Token* t;
|
const Token* t;
|
||||||
bool found;
|
bool found;
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
Settings settings2;
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
vartok = nullptr;
|
vartok = nullptr;
|
||||||
|
@ -96,6 +97,7 @@ private:
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
LOAD_LIB_2(settings.library, "std.cfg");
|
LOAD_LIB_2(settings.library, "std.cfg");
|
||||||
|
settings2.platform(Settings::Unspecified);
|
||||||
|
|
||||||
TEST_CASE(array);
|
TEST_CASE(array);
|
||||||
TEST_CASE(stlarray);
|
TEST_CASE(stlarray);
|
||||||
|
@ -3118,12 +3120,10 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string typeOf(const char code[], const char str[], const char filename[] = "test.cpp") {
|
std::string typeOf(const char code[], const char str[], const char filename[] = "test.cpp") {
|
||||||
Settings s;
|
Tokenizer tokenizer(&settings2, this);
|
||||||
s.platform(Settings::Unspecified);
|
|
||||||
Tokenizer tokenizer(&s, this);
|
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize(istr, filename);
|
tokenizer.tokenize(istr, filename);
|
||||||
const Token * const tok = Token::findsimplematch(tokenizer.tokens(),str);
|
const Token * const tok = Token::findsimplematch(tokenizer.tokens(), str);
|
||||||
return tok->valueType() ? tok->valueType()->str() : std::string();
|
return tok->valueType() ? tok->valueType()->str() : std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3226,6 +3226,9 @@ private:
|
||||||
// struct member..
|
// struct member..
|
||||||
ASSERT_EQUALS("signed int", typeOf("struct AB { int a; int b; } ab; x = ab.a;", "."));
|
ASSERT_EQUALS("signed int", typeOf("struct AB { int a; int b; } ab; x = ab.a;", "."));
|
||||||
ASSERT_EQUALS("signed int", typeOf("struct AB { int a; int b; } *ab; x = ab[1].a;", "."));
|
ASSERT_EQUALS("signed int", typeOf("struct AB { int a; int b; } *ab; x = ab[1].a;", "."));
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
ASSERT_EQUALS("signed int", typeOf("struct AB { static int a; }; x = AB::a;", "::"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue