From cae19cadd333be9c56079cb5a511b8b8885fd37f Mon Sep 17 00:00:00 2001 From: PKEuS Date: Thu, 4 Feb 2016 20:49:13 +0100 Subject: [PATCH] ValueType: Added support for static member variables and simplified code --- lib/symboldatabase.cpp | 44 ++++++++++++++++++++++--------------- test/testio.cpp | 6 ++--- test/testsymboldatabase.cpp | 11 ++++++---- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 77938219e..26ec21364 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3676,12 +3676,15 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value Token *parent = const_cast(tok->astParent()); if (!parent || parent->valueType()) return; - if (!parent->astOperand1() || !parent->astOperand1()->valueType()) + if (!parent->astOperand1()) return; - if (Token::Match(parent, "<<|>>")) { - if (!cpp || (parent->astOperand2() && parent->astOperand2()->valueType() && parent->astOperand2()->valueType()->isIntegral())) - setValueType(parent, *parent->astOperand1()->valueType(), cpp, defaultSignedness); + const ValueType *vt1 = parent->astOperand1() ? parent->astOperand1()->valueType() : nullptr; + const ValueType *vt2 = parent->astOperand2() ? parent->astOperand2()->valueType() : nullptr; + + if (vt1 && Token::Match(parent, "<<|>>")) { + if (!cpp || (vt2 && vt2->isIntegral())) + setValueType(parent, *vt1, cpp, defaultSignedness); return; } @@ -3706,26 +3709,31 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value return; } - if (parent->str() == "." && - valuetype.typeScope && - parent->astOperand2() && parent->astOperand2()->isName() && !parent->astOperand2()->valueType()) { - const std::string &name = parent->astOperand2()->str(); - const Scope *typeScope = parent->astOperand1()->valueType()->typeScope; - if (!typeScope) - return; - for (std::list::const_iterator it = typeScope->varlist.begin(); it != typeScope->varlist.end(); ++it) { - const Variable &var = *it; - if (var.nameToken()->str() == name) { - setValueType(parent, var, cpp, defaultSignedness); + if ((parent->str() == "." || parent->str() == "::") && + parent->astOperand2() && parent->astOperand2()->isName()) { + const Variable* var = parent->astOperand2()->variable(); + if (!var && valuetype.typeScope && vt1) { + const std::string &name = parent->astOperand2()->str(); + const Scope *typeScope = vt1->typeScope; + if (!typeScope) return; + for (std::list::const_iterator it = typeScope->varlist.begin(); it != typeScope->varlist.end(); ++it) { + if (it->nameToken()->str() == name) { + var = &*it; + break; + } } } + if (var) + setValueType(parent, *var, cpp, defaultSignedness); + return; } - if (parent->astOperand2() && !parent->astOperand2()->valueType()) + if (!vt1) return; - const ValueType *vt1 = parent->astOperand1()->valueType(); - const ValueType *vt2 = parent->astOperand2() ? parent->astOperand2()->valueType() : nullptr; + if (parent->astOperand2() && !vt2) + return; + if (parent->isArithmeticalOp() && vt2) { if (vt1->pointer != 0U && vt2->pointer == 0U) { setValueType(parent, *vt1, cpp, defaultSignedness); diff --git a/test/testio.cpp b/test/testio.cpp index 23550a54e..750222e31 100644 --- a/test/testio.cpp +++ b/test/testio.cpp @@ -1648,11 +1648,11 @@ private: " 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" - "[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) %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. 6) requires 'double' but the argument type is 'int'.\n", errout.str()); + "[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 'signed int'.\n", errout.str()); 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()); }"); diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 3c34df4c4..9f700fd1e 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -49,6 +49,7 @@ private: const Token* t; bool found; Settings settings; + Settings settings2; void reset() { vartok = nullptr; @@ -96,6 +97,7 @@ private: void run() { LOAD_LIB_2(settings.library, "std.cfg"); + settings2.platform(Settings::Unspecified); TEST_CASE(array); TEST_CASE(stlarray); @@ -3118,12 +3120,10 @@ private: } std::string typeOf(const char code[], const char str[], const char filename[] = "test.cpp") { - Settings s; - s.platform(Settings::Unspecified); - Tokenizer tokenizer(&s, this); + Tokenizer tokenizer(&settings2, this); std::istringstream istr(code); 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(); } @@ -3226,6 +3226,9 @@ private: // 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[1].a;", ".")); + + // Static members + ASSERT_EQUALS("signed int", typeOf("struct AB { static int a; }; x = AB::a;", "::")); } };